diff --git a/.backportrc.json b/.backportrc.json index 7a53c3a60811c4..cdd0e736aeba96 100644 --- a/.backportrc.json +++ b/.backportrc.json @@ -1,5 +1,5 @@ { "upstream": "elastic/kibana", - "branches": [{ "name": "6.x", "checked": true }, "6.2", "6.1", "6.0", "5.6"], + "branches": [{ "name": "6.x", "checked": true }, "6.3", "6.2", "6.1", "6.0", "5.6"], "labels": ["backport"] } diff --git a/.eslintrc.js b/.eslintrc.js index c5a22335a4fdf3..2995d4fc8ac60e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,7 +9,15 @@ module.exports = { ], settings: { - 'import/resolver': 'eslint-import-resolver-node', + 'import/resolver': { + '@kbn/eslint-import-resolver-kibana': { + forceNode: true, + }, + }, + + react: { + version: '16.3', + }, }, overrides: [ @@ -27,6 +35,7 @@ module.exports = { 'packages/kbn-plugin-helpers/**/*', 'packages/kbn-plugin-generator/**/*', 'packages/kbn-test-subj-selector/**/*', + 'packages/kbn-test/**/*', 'packages/kbn-eslint-import-resolver-kibana/**/*', 'x-pack/plugins/apm/**/*', ], @@ -65,10 +74,11 @@ module.exports = { // instructs import/no-extraneous-dependencies to treat modules // in plugins/ or ui/ namespace as "core modules" so they don't // trigger failures for not being listed in package.json - 'import/core-modules': ['plugins', 'ui'], + 'import/core-modules': ['plugins', 'ui', 'uiExports'], 'import/resolver': { '@kbn/eslint-import-resolver-kibana': { + forceNode: false, rootPackageName: 'kibana', kibanaPath: '.', pluginMap: readdirSync(resolve(__dirname, 'x-pack/plugins')).reduce( @@ -86,7 +96,7 @@ module.exports = { }, /** - * files that ARE NOT allowed to use devDepenedncies + * Files that ARE NOT allowed to use devDependencies */ { files: ['packages/kbn-ui-framework/**/*', 'x-pack/**/*'], @@ -102,7 +112,7 @@ module.exports = { }, /** - * files that ARE allowed to use devDepenedncies + * Files that ARE allowed to use devDependencies */ { files: [ @@ -128,7 +138,39 @@ module.exports = { }, /** - * Files that are not transpiled with babel + * Files that run BEFORE node version check + */ + { + files: ['scripts/**/*', 'src/setup_node_env/**/*'], + rules: { + 'import/no-commonjs': 'off', + 'prefer-object-spread/prefer-object-spread': 'off', + 'no-var': 'off', + 'prefer-const': 'off', + 'prefer-destructuring': 'off', + 'no-restricted-syntax': [ + 'error', + 'ImportDeclaration', + 'ExportNamedDeclaration', + 'ExportDefaultDeclaration', + 'ExportAllDeclaration', + 'ArrowFunctionExpression', + 'AwaitExpression', + 'ClassDeclaration', + 'RestElement', + 'SpreadElement', + 'YieldExpression', + 'VariableDeclaration[kind="const"]', + 'VariableDeclaration[kind="let"]', + 'VariableDeclarator[id.type="ArrayPattern"]', + 'VariableDeclarator[id.type="ObjectPattern"]', + ], + }, + }, + + /** + * Files that run AFTER node version check + * and are not also transpiled with babel */ { files: [ @@ -155,6 +197,43 @@ module.exports = { }, }, + /** + * Files that require Apache 2.0 headers, settings + * are overriden below for files that require Elastic + * Licence headers + */ + { + files: ['**/*.js'], + plugins: ['@kbn/eslint-plugin-license-header'], + rules: { + '@kbn/license-header/require-license-header': [ + 'error', + { + license: dedent` + /* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + `, + }, + ], + }, + }, + /** * X-Pack global overrides */ @@ -166,7 +245,7 @@ module.exports = { }, /** - * Files that require the license headers + * Files that require Elastic license headers instead of Apache 2.0 header */ { files: ['x-pack/**/*.js'], diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 00000000000000..8502d9be5b56c2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,34 @@ +--- +name: Bug report +about: Things break. Help us identify those things so we can fix them! + +--- + +**Kibana version:** + +**Elasticsearch version:** + +**Server OS version:** + +**Browser version:** + +**Browser OS version:** + +**Original install method (e.g. download page, yum, from source, etc.):** + +**Describe the bug:** + +**Steps to reproduce:** +1. +2. +3. + +**Expected behavior:** + +**Screenshots (if relevant):** + +**Errors in browser console (if relevant):** + +**Provide logs and/or server output (if relevant):** + +**Any additional context:** diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 00000000000000..e627a805aeb1ff --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,9 @@ +--- +name: Feature request +about: Kibana can't do all the things, but maybe it can do your things. + +--- + +**Describe the feature:** + +**Describe a specific use case for the feature:** diff --git a/.github/ISSUE_TEMPLATE/Question.md b/.github/ISSUE_TEMPLATE/Question.md new file mode 100644 index 00000000000000..38fcb7af30b476 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Question.md @@ -0,0 +1,15 @@ +--- +name: Question +about: Who, what, when, where, and how? + +--- + +Hey, stop right there! + +We use GitHub to track feature requests and bug reports. Please do not submit issues for questions about how to use features of Kibana, how to set Kibana up, best practices, or development related help. + +However, we do want to help! Head on over to our official Kibana forums and ask your questions there. In additional to awesome, knowledgeable community contributors, core Kibana developers are on the forums every single day to help you out. + +The forums are here: https://discuss.elastic.co/c/kibana + +We can't stop you from opening an issue here, but it will likely linger without a response for days or weeks before it is closed and we ask you to join us on the forums instead. Save yourself the time, and ask on the forums today. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ca48d2038b1ab5..2188e39124c615 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -176,7 +176,7 @@ Start elasticsearch from a nightly snapshot. yarn es snapshot ``` -This will run Elasticsearch with a `trial` license and bootstraped with the user `elastic` and password `changeme`. Additional options are available, pass `--help` for more information. +This will run Elasticsearch with a `basic` license. Additional options are available, pass `--help` for more information. > You'll need to have a `java` binary in `PATH` or set `JAVA_HOME`. @@ -195,7 +195,7 @@ Start the development server. > On Windows, you'll need you use Git Bash, Cygwin, or a similar shell that exposes the `sh` command. And to successfully build you'll need Cygwin optional packages zip, tar, and shasum. -Now you can point your web browser to https://localhost:5601 and start using Kibana! When running `yarn start`, Kibana will also log that it is listening on port 5603 due to the base path proxy, but you should still access Kibana on port 5601. +Now you can point your web browser to http://localhost:5601 and start using Kibana! When running `yarn start`, Kibana will also log that it is listening on port 5603 due to the base path proxy, but you should still access Kibana on port 5601. #### Running Kibana in Open-Source mode @@ -265,8 +265,29 @@ Once that's done, just run: yarn test && yarn build --skip-os-packages ``` +You can get all build options using the following command: + +```bash +yarn build --help +``` + ### Debugging Server Code -`yarn debug` will start the server with Node's inspect and debug-brk flags. Kibana's development mode will start three processes. Chrome's developer tools can be configured to connect to all three under the connection tab. +`yarn debug` will start the server with Node's inspect flag. Kibana's development mode will start three processes. Chrome's developer tools can be configured to connect to all three under the connection tab. + +### Unit testing frameworks +Kibana is migrating unit testing from Mocha to Jest. Legacy unit tests still exist in Mocha but all new unit tests should be written in Jest. + +#### Mocha (legacy) +Mocha tests are contained in `__tests__` directories. + +#### Jest +Jest tests are stored in the same directory as source code files with the `.test.js` suffix. + +### Running Jest Unit Tests + +```bash +node scripts/jest +``` ### Debugging Unit Tests @@ -342,6 +363,7 @@ yarn test:browser --dev # remove the --dev flag to run them once and close [Read about the `FunctionalTestRunner`](https://www.elastic.co/guide/en/kibana/current/development-functional-tests.html) to learn more about how you can run and develop functional tests for Kibana core and plugins. +You can also look into the [Scripts README.md](./scripts/README.md) to learn more about using the node scripts we provide for building Kibana, running integration tests, and starting up Kibana and Elasticsearch while you develop. ### Building OS packages diff --git a/Gruntfile.js b/Gruntfile.js index 476513a650d106..e98708b87e3a70 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,4 +1,23 @@ -require('./src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('./src/setup_node_env'); module.exports = function (grunt) { // set the config once before calling load-grunt-config diff --git a/NOTICE.txt b/NOTICE.txt index e7bfa9ae800f79..3a530b5323b4ff 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -31,6 +31,26 @@ THE SOFTWARE. This product uses Noto fonts that are licensed under the SIL Open Font License, Version 1.1. +--- +Pretty handling of logarithmic axes. +Copyright (c) 2007-2014 IOLA and Ole Laursen. +Licensed under the MIT license. +Created by Arne de Laat +Set axis.mode to "log" and make the axis logarithmic using transform: + axis: { + mode: 'log', + transform: function(v) {v <= 0 ? Math.log(v) / Math.LN10 : null}, + inverseTransform: function(v) {Math.pow(10, v)} + } +The transform filters negative and zero values, because those are +invalid on logarithmic scales. +This plugin tries to create good looking logarithmic ticks, using +unicode superscript characters. If all data to be plotted is between two +powers of ten then the default flot tick generator and renderer are +used. Logarithmic ticks are places at powers of ten and at half those +values if there are not to many ticks already (e.g. [1, 5, 10, 50, 100]). +For details, see https://github.com/flot/flot/pull/1328 + --- This product bundles angular-ui-bootstrap@0.12.1 which is available under a "MIT" license. diff --git a/README.md b/README.md index 2369a52cbe6518..bebead95d50931 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ _Note: The version numbers below are only examples, meant to illustrate the rela ## Questions? Problems? Suggestions? -- If you've found a bug or want to request a feature, please create a [GitHub Issue](https://github.com/elastic/kibana/issues/new). +- If you've found a bug or want to request a feature, please create a [GitHub Issue](https://github.com/elastic/kibana/issues/new/choose). Please check to make sure someone else hasn't already created an issue for the same topic. - Need help using Kibana? Ask away on our [Kibana Discuss Forum](https://discuss.elastic.co/c/kibana) and a fellow community member or Elastic engineer will be glad to help you out. diff --git a/config/kibana.yml b/config/kibana.yml index 17d98e141f52c7..b5324b208f144a 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -86,6 +86,9 @@ # Time in milliseconds to wait for Elasticsearch at Kibana startup before retrying. #elasticsearch.startupTimeout: 5000 +# Logs queries sent to Elasticsearch. Requires logging.verbose set to true. +#elasticsearch.logQueries: false + # Specifies the path where Kibana creates the process ID file. #pid.file: /var/run/kibana.pid diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc new file mode 100644 index 00000000000000..f3ac819f430f31 --- /dev/null +++ b/docs/CHANGELOG.asciidoc @@ -0,0 +1,46 @@ +[[release-notes]] += {kib} Release Notes +++++ +Release Notes +++++ + +[partintro] +-- +// Use these for links to issue and pulls. Note issues and pulls redirect one to +// each other on Github, so don't worry too much on using the right prefix. +:issue: https://github.com/elastic/kibana/issues/ +:pull: https://github.com/elastic/kibana/pull/ + +This section summarizes the changes in each release. + +* <> + +-- + +[[release-notes-7.0.0]] +== {kib} 7.0.0 + +//[float] +//[[breaking-7.0.0]] +//=== Breaking Changes + +//[float] +//=== Breaking Java Changes + +//[float] +//=== Deprecations + +//[float] +//=== New Features + +//[float] +//=== Enhancements + +//[float] +//=== Bug Fixes + +//[float] +//=== Regressions + +//[float] +//=== Known Issues diff --git a/docs/api.asciidoc b/docs/api.asciidoc new file mode 100644 index 00000000000000..cc89999d5e6a7e --- /dev/null +++ b/docs/api.asciidoc @@ -0,0 +1,33 @@ +[[api]] += REST API + +[partintro] +-- +Some of the features of Kibana are provided via a REST API, which is ideal for +people that want to create an integration with Kibana or that want to automate +certain aspects of configuring and deploying Kibana. + +Each API in this documentation should be clearly marked as either `stable`, +`beta`, or `experimental`. If an API is not marked, it should be considered +`experimental`. + +What do these labels mean? + +* *Stable* APIs should be safe to use extensively in production. Any breaking +changes to these APIs should only occur in major versions and will be +clearly documented in the breaking changes documentation for that release. +* *Beta* APIs are on track to become stable, permanent features of Kibana. +Caution should be exercised in their use since it is possible we'd have to make +a breaking change to these APIs in a minor version, but we'll avoid this +wherever possible. +* *Experimental* APIs are just that - an experiment. An experimental API might +have breaking changes in any version of Kibana, or it might even be removed +entirely. + +[float] +== APIs + +* <> +-- + +include::api/saved-objects.asciidoc[] \ No newline at end of file diff --git a/docs/api/saved-objects.asciidoc b/docs/api/saved-objects.asciidoc new file mode 100644 index 00000000000000..45ed53616312cc --- /dev/null +++ b/docs/api/saved-objects.asciidoc @@ -0,0 +1,24 @@ +[[saved-objects-api]] +== Saved Objects API + +The saved objects API allows people to manage Kibana saved objects, including +but not limited to dashboards, visualizations, and index patterns. + +Traditionally, developers would perform this level of integration by writing +documents directly to the `.kibana` index. *Do not do this!* Writing directly +to the `.kibana` index is not safe and it _will_ result in corrupted data that +permanently breaks Kibana in a future version. + +* <> +* <> +* <> +* <> +* <> +* <> + +include::saved-objects/get.asciidoc[] +include::saved-objects/bulk_get.asciidoc[] +include::saved-objects/find.asciidoc[] +include::saved-objects/create.asciidoc[] +include::saved-objects/update.asciidoc[] +include::saved-objects/delete.asciidoc[] diff --git a/docs/api/saved-objects/bulk_get.asciidoc b/docs/api/saved-objects/bulk_get.asciidoc new file mode 100644 index 00000000000000..f741410aa87dea --- /dev/null +++ b/docs/api/saved-objects/bulk_get.asciidoc @@ -0,0 +1,81 @@ +[[saved-objects-api-bulk-get]] +=== Bulk Get Objects + +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] + +The bulk-get saved object API enables you to retrieve multiple Kibana saved +objects by id. + +==== Request + +`POST /api/saved_objects/_bulk_get` + +==== Request Body + +The request body must be a JSON array containing objects, each of which +contains the following properties: + +`type` (required):: + (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` + +`id` (required):: + (string) ID of object to retrieve + +==== Response body + +The response body will have a top level `saved_objects` property that contains +an array of objects, which represent the response for each of the requested +objects. The order of the objects in the response is identical to the order of +the objects in the request. + +For any saved object that could not be found, an error object will exist in its +place. + +==== Examples + +The following example attempts to retrieve an index pattern with id +`my-pattern` and a dashboard with id `my-dashboard`, but only the index pattern +exists. + +[source,js] +-------------------------------------------------- +POST api/saved_objects/_bulk_get +[ + { + "type": "index-pattern", + "id": "my-pattern" + }, + { + "type": "dashboard", + "id": "my-dashboard" + } +] +-------------------------------------------------- +// KIBANA + +A successful call returns a response code of `200` and a response body +containing a JSON structure similar to the following example: + +[source,js] +-------------------------------------------------- +{ + "saved_objects": [ + { + "id": "my-pattern", + "type": "index-pattern", + "version": 1, + "attributes": { + "title": "my-pattern-*" + } + }, + { + "id": "my-dashboard", + "type": "dashboard", + "error": { + "statusCode": 404, + "message": "Not found" + } + } + ] +} +-------------------------------------------------- diff --git a/docs/api/saved-objects/create.asciidoc b/docs/api/saved-objects/create.asciidoc new file mode 100644 index 00000000000000..0a8ae9d7c636d1 --- /dev/null +++ b/docs/api/saved-objects/create.asciidoc @@ -0,0 +1,73 @@ +[[saved-objects-api-create]] +=== Create Object + +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] + +The create saved object API enables you to persist a Kibana saved object. + +==== Request + +`POST /api/saved_objects/` + + +`POST /api/saved_objects//` + +==== Path Parameters + +`type` (required):: + (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` + +`id` (optional):: + (string) Enables specifying an ID to use, as opposed to one being randomly generated + + +==== Query Parameters + +`overwrite` (optional):: + (boolean) If true, will overwrite the document with the same ID. + + +==== Request Body + +`attributes` (required):: + (object) The data to persist + + +==== Examples + +The following example creates an index pattern object with a pattern of +`my-pattern-*`. + +[source,js] +-------------------------------------------------- +POST api/saved_objects/index-pattern/my-pattern +{ + "attributes": { + "title": "my-pattern-*" + } +} +-------------------------------------------------- +// KIBANA + +A successful call returns a response code of `200` and a response body +containing a JSON structure similar to the following example: + +[source,js] +-------------------------------------------------- +{ + "id": "my-pattern", <1> + "type": "index-pattern", + "version": 1, + "attributes": { + "title": "my-pattern-*" + } +} +-------------------------------------------------- + +<1> If `my-pattern` was not specified in the path, a unique ID would have been +generated. + +==== Known issues + +1. *Attributes are not validated at creation time*. This means you can pass +arbitrary and ill-formed data into this API that can break Kibana. Make sure +any data you send to this API is properly formed. diff --git a/docs/api/saved-objects/delete.asciidoc b/docs/api/saved-objects/delete.asciidoc new file mode 100644 index 00000000000000..1c75321e1c73ee --- /dev/null +++ b/docs/api/saved-objects/delete.asciidoc @@ -0,0 +1,32 @@ +[[saved-objects-api-delete]] +=== Delete Object + +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] + +The delete saved object API permanently removes a Kibana saved object. Once a +saved object has been deleted, _it cannot be recovered_. + +==== Request + +`DELETE /api/saved_objects//` + +==== Path Parameters + +`type` (required):: + (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` + +`id` (required):: + (string) Object ID being removed + + +==== Examples + +The following example deletes an index pattern object with an ID of `my-pattern` + +[source,js] +-------------------------------------------------- +DELETE api/saved_objects/index-pattern/my-pattern +-------------------------------------------------- +// KIBANA + +A successful call returns a response code of `200`. diff --git a/docs/api/saved-objects/find.asciidoc b/docs/api/saved-objects/find.asciidoc new file mode 100644 index 00000000000000..e42f3214965790 --- /dev/null +++ b/docs/api/saved-objects/find.asciidoc @@ -0,0 +1,84 @@ +[[saved-objects-api-find]] +=== Find Objects + +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] + +The find saved object API enables you to retrieve a paginated set of Kibana +saved objects by various conditions. + +==== Request + +`GET /api/saved_objects/_find` + +==== Query Parameters + +`per_page` (optional):: + (number) The number of objects to return per page +`page` (optional):: + (number) The page of objects to return +`type` (optional):: + (array|string) The saved object type(s) that the response should be limited to +`search` (optional):: + (string) A {ref}/query-dsl-simple-query-string-query.html[simple_query_string] Elasticsearch query to filter the objects in the response +`search_fields` (optional):: + (array|string) The fields to perform the `simple_query_string` parsed query against +`fields` (optional):: + (array|string) The fields to return in the response +`sort_field` (optional):: + (string) The field on which the response will be sorted + +[NOTE] +============================================== + +As objects change in Kibana, the results on each page of this response can +change. This makes the `find` API suitable for traditional paginated results +but not a reliable way to safely export large amounts of data. + +============================================== + + +==== Examples + +The following example attempts to find index patterns with titles that start +with `my`: + +[source,js] +-------------------------------------------------- +GET api/saved_objects/_find?type=index-pattern&search_fields=title&search=my* +-------------------------------------------------- +// KIBANA + +A successful call returns a response code of `200` and a response body +containing a JSON structure similar to the following example: + +[source,js] +-------------------------------------------------- +{ + "total": 1, + "data": [ + { + "id": "my-pattern", + "type": "index-pattern", + "version": 1, + "attributes": { + "title": "my-pattern-*" + } + } + ] +} +-------------------------------------------------- + +[NOTE] +.Multiple values for a parameter +============================================== + +For parameters that can accept multiple values (e.g. `fields`), repeat the +query parameter for each value: + +[source,js] +-------------------------------------------------- +GET api/saved_objects/_find?fields=id&fields=title +-------------------------------------------------- +// KIBANA + +============================================== diff --git a/docs/api/saved-objects/get.asciidoc b/docs/api/saved-objects/get.asciidoc new file mode 100644 index 00000000000000..669936657a3938 --- /dev/null +++ b/docs/api/saved-objects/get.asciidoc @@ -0,0 +1,46 @@ +[[saved-objects-api-get]] +=== Get Object + +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] + +The get saved object API enables you to retrieve a single Kibana saved object +by id. + +==== Request + +`GET /api/saved_objects//` + +==== Path Parameters + +`type` (required):: + (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` + +`id` (required):: + (string) ID of object to retrieve + + +==== Examples + +The following example retrieves the index pattern object with an id of +`my-pattern`. + +[source,js] +-------------------------------------------------- +GET api/saved_objects/index-pattern/my-pattern +-------------------------------------------------- +// KIBANA + +A successful call returns a response code of `200` and a response body +containing a JSON structure similar to the following example: + +[source,js] +-------------------------------------------------- +{ + "id": "my-pattern", + "type": "index-pattern", + "version": 1, + "attributes": { + "title": "my-pattern-*" + } +} +-------------------------------------------------- diff --git a/docs/api/saved-objects/update.asciidoc b/docs/api/saved-objects/update.asciidoc new file mode 100644 index 00000000000000..5c47e447c2881c --- /dev/null +++ b/docs/api/saved-objects/update.asciidoc @@ -0,0 +1,63 @@ +[[saved-objects-api-update]] +=== Update Object + +experimental[This functionality is *experimental* and may be changed or removed completely in a future release.] + +The update saved object API enables you to update the attributes for an +existing Kibana saved object. + +==== Request + +`PUT /api/saved_objects//` + +==== Path Parameters + +`type` (required):: + (string) Valid options, include: `visualization`, `dashboard`, `search`, `index-pattern`, `config`, and `timelion-sheet` + +`id` (required):: + (string) ID of object to update + + +==== Request Body + +`attributes` (required):: + (object) The data to persist + + +==== Examples + +The following example updates an existing index pattern object identified as +`my-pattern` with a different index pattern title. + +[source,js] +-------------------------------------------------- +PUT api/saved_objects/index-pattern/my-pattern +{ + "attributes": { + "title": "some-other-pattern-*" + } +} +-------------------------------------------------- +// KIBANA + +A successful call returns a response code of `200` and a response body +containing a JSON structure similar to the following example: + +[source,js] +-------------------------------------------------- +{ + "id": "my-pattern", + "type": "index-pattern", + "version": 2, + "attributes": { + "title": "some-other-pattern-*" + } +} +-------------------------------------------------- + +==== Known issues + +1. *Attributes are not validated at update time*. This means you can pass +arbitrary and ill-formed data into this API that can break Kibana. Make sure +any data you send to this API is properly formed. diff --git a/x-pack/docs/en/apm/bottlenecks.asciidoc b/docs/apm/bottlenecks.asciidoc similarity index 100% rename from x-pack/docs/en/apm/bottlenecks.asciidoc rename to docs/apm/bottlenecks.asciidoc diff --git a/x-pack/docs/en/apm/getting-started.asciidoc b/docs/apm/getting-started.asciidoc similarity index 100% rename from x-pack/docs/en/apm/getting-started.asciidoc rename to docs/apm/getting-started.asciidoc diff --git a/x-pack/docs/en/apm/images/apm-setup.jpg b/docs/apm/images/apm-setup.jpg similarity index 100% rename from x-pack/docs/en/apm/images/apm-setup.jpg rename to docs/apm/images/apm-setup.jpg diff --git a/x-pack/docs/en/apm/images/apm-transaction.png b/docs/apm/images/apm-transaction.png similarity index 100% rename from x-pack/docs/en/apm/images/apm-transaction.png rename to docs/apm/images/apm-transaction.png diff --git a/x-pack/docs/en/apm/index.asciidoc b/docs/apm/index.asciidoc similarity index 100% rename from x-pack/docs/en/apm/index.asciidoc rename to docs/apm/index.asciidoc diff --git a/docs/dashboard.asciidoc b/docs/dashboard.asciidoc index e62ddc7af777eb..1d03b9b3473319 100644 --- a/docs/dashboard.asciidoc +++ b/docs/dashboard.asciidoc @@ -3,163 +3,116 @@ [partintro] -- -A Kibana _dashboard_ displays a collection of saved visualizations. +A Kibana _dashboard_ displays a collection of visualizations and searches. +You can arrange, resize, and edit the dashboard content and then save the dashboard +so you can share it. -.Sample dashboard. -image:images/tutorial-dashboard.png[Example dashboard] +[role="screenshot"] +image:images/Dashboard_example.png[Example dashboard] -In edit mode you can arrange and resize the visualizations as needed and save dashboards so -they be reloaded and shared. - -.Edit mode -image:images/Dashboard-Tutorial-Edit-Mode.png[Example dashboard in edit mode] -- [[dashboard-getting-started]] == Building a Dashboard -To build a dashboard: - -. Click *Dashboard* in the side navigation. If you haven't previously viewed a -dashboard, Kibana displays a landing page where you can click *+*. -Otherwise, click the *Dashboard* breadcrumb to navigate back to the landing page. -+ -image:images/Dashboard-Landing-Page.png[Dashboard Landing Page] +. In the side navigation, click *Dashboard*. +. Click *Create new dashboard.* +. Click *Add*. [[adding-visualizations-to-a-dashboard]] -. To add a visualization to the dashboard, click *Edit* mode. -Brand new dashboards will be in *Edit* mode automatically. +. To add a visualization, select its name from the list of visualizations +or click *Add new visualization* to create one. +If you have a large number of visualizations, you can filter the list. + -image:images/Dashboard-View-Mode.png[Dashboard View Mode] +[role="screenshot"] +image:images/Dashboard_add_visualization.png[Example add visualization to dashboard] -. Once in Edit mode, click *Add* and select the -visualization. If you have a large number of visualizations, you can enter a -*Filter* string to filter the list. -+ -image:images/Dashboard-Edit-Mode.png[Dashboard Edit Mode] -+ -Kibana displays the selected visualization in a container on the dashboard. -If you see a message that the container is too small, you can -<>. -+ -NOTE: By default, Kibana dashboards use a light color theme. To use a dark color theme, -click *Options* and select *Use dark theme*. To change the default theme, go -to *Management/Kibana/Advanced Settings* and set `dashboard:defaultDarkTheme` -to `true`. +. To add a saved search, click the *Saved Search* tab, and then select a name from the list. [[saving-dashboards]] -. When you're done adding and arranging visualizations, click *Save* to save the -dashboard: -.. Enter a name for the dashboard. -.. To store the time period specified in the time filter with the dashboard, select -*Store time with dashboard*. -.. Click the *Save* button to store it as a Kibana saved object. - -[float] -[[customizing-your-dashboard]] -=== Arranging Dashboard Elements +. When you're finished adding and arranging the dashboard content, +go to the menu bar, click *Save*, and enter +a name. Optionally, you can store the time period specified in the time +filter by selecting *Store time with dashboard*. -In *Edit Mode*, visualizations in your dashboard are stored in resizable, moveable containers. +By default, Kibana dashboards use a light color theme. To use a dark color theme, +click *Options* and select *Use dark theme*. To set the dark theme as the default, go +to *Management > Advanced Settings* and set `dashboard:defaultDarkTheme` +to `On`. -[float] -[[moving-containers]] -==== Moving Visualizations +[[loading-a-saved-dashboard]] +TIP: You can import, export, and delete dashboards in *Kibana > Management > +Saved Objects > Dashboards*. -To reposition a visualization: +[[customizing-your-dashboard]] +== Arranging Dashboard Elements -. Hover over it to display the container controls. -. Click and hold the *Move* button in the upper right corner of the container. -. Drag the container to its new position. -. Release the *Move* button. +The visualizations and searches in a dashboard are stored in panels that you can move, +resize, and delete. To start editing, open the dashboard and click *Edit* +in the menu bar. -[float] -[[resizing-containers]] -==== Resizing Visualizations +[role="screenshot"] +image:images/Dashboard_Resize_Menu.png[Example dashboard] -To resize a visualization: +[[moving-containers]] +To move a panel, click and hold the +header of a panel and drag to the new location. -. Hover over it to display the container controls. -. Click and hold the *Resize* button in the bottom right corner of the container. -. Drag to change the dimensions of the container. -. Release the *Resize* button. +[[resizing-containers]] +To resize a panel, click the resize control on the lower right and drag +to the new dimensions. -[float] [[removing-containers]] -==== Removing Visualizations - -To remove a visualization from the dashboard: +Additional commands for managing the +panel and its contents are in the gear menu in the upper right. -. Hover over it to display the container controls. -. Click the *Delete* button in the upper right corner of the container. -+ -NOTE: Removing a visualization from a dashboard does _not_ delete the -saved visualization. +NOTE: Deleting a panel from a +dashboard does *not* delete the saved visualization or search. -[float] [[viewing-detailed-information]] -=== Viewing Visualization Data +== Viewing Visualization Data -To display the raw data behind a visualization: +If your visualization supports it, you can display the raw data behind +the visualization using the Expand/Collapse button. -. Hover over it to display the container controls. -. Click the *Expand* button in the lower left corner of the container. -This displays a table that contains the underlying data. You can also view -the raw Elasticsearch request and response in JSON and the request statistics. -The request statistics show the query duration, request duration, total number -of matching records, and the index (or index pattern) that was searched. +. Open the dashboard. +. Hover over the visualization and click the *Expand* button in the lower +left. ++ +The underlying data is displayed in a table. You can also view +the raw Elasticsearch request, the response in JSON, and the request statistics. +These statistics show the query duration, request duration, total number +of matching records, and the index that was searched. + -image:images/NYCTA-Table.jpg[] +[role="screenshot"] +image:images/Dashboard_visualization_data.png[Example of visualization data] -To export the data behind the visualization as a comma-separated-values -(CSV) file, click the *Raw* or *Formatted* link at the bottom of the data -Table. *Raw* exports the data as it is stored in Elasticsearch. *Formatted* -exports the results of any applicable Kibana <>. To return to the visualization, click the *Collapse* button in the lower left -corner of the container. - -[float] -[[changing-the-visualization]] -=== Modifying a Visualization - -To open a visualization in the Visualization Editor: - -. Enter Edit Mode. -. Hover over it to display the container controls. -. Click the *Edit* button in the upper right corner of the container. - - -[[loading-a-saved-dashboard]] -== Loading a Dashboard - -To open a saved dashboard: - -. Click *Dashboard* in the side navigation. -. Click *Open* and select a dashboard. If you have a large number of -dashboards, you can enter a *Filter* string to filter the list. -+ -TIP: To import, export, and delete dashboards, click the *Manage Dashboards* link -to open *Management/Kibana/Saved Objects/Dashboards*. +corner. [[sharing-dashboards]] == Sharing a Dashboard -You can either share a direct link to a Kibana dashboard with another user, +You can either share a direct link to a Kibana dashboard, or embed the dashboard in a web page. Users must have Kibana access -to view embedded dashboards. +to view an embedded dashboard. [[embedding-dashboards]] -To share a dashboard: -. Click *Dashboard* in the side navigation. . Open the dashboard you want to share. -. Click *Share*. -. Copy the link you want to share or the iframe you want to embed. You can -share the live dashboard or a static snapshot of the current point in time. -+ -TIP: When sharing a link to a dashboard snapshot, use the *Short URL*. Snapshot -URLs are long and can be problematic for Internet Explorer users and other -tools. +. In the menu bar, click *Share*. +. Copy the link you want to share or the iframe you want to embed. You can +share the live dashboard or a static snapshot of the current point in time. +TIP: You can create a link to a dashboard by title by doing this: + +`${domain}/${basepath?}/app/kibana#/dashboards?title=${yourdashboardtitle}` +TIP: When sharing a link to a dashboard snapshot, use the *Short URL*. Snapshot +URLs are long and can be problematic for Internet Explorer and other +tools. To create a short URL, you must have write access to `.kibana`. diff --git a/docs/index-shared4.asciidoc b/docs/dev-tools.asciidoc similarity index 51% rename from docs/index-shared4.asciidoc rename to docs/dev-tools.asciidoc index 5b8e8ae130eb40..d4d827960376a2 100644 --- a/docs/index-shared4.asciidoc +++ b/docs/dev-tools.asciidoc @@ -8,4 +8,8 @@ The *Dev Tools* page contains development tools that you can use to interact with your data in Kibana. -- -include::console.asciidoc[] +include::dev-tools/console/console.asciidoc[] + +include::dev-tools/searchprofiler/index.asciidoc[] + +include::dev-tools/grokdebugger/index.asciidoc[] diff --git a/docs/console/auto-formatting.asciidoc b/docs/dev-tools/console/auto-formatting.asciidoc similarity index 100% rename from docs/console/auto-formatting.asciidoc rename to docs/dev-tools/console/auto-formatting.asciidoc diff --git a/docs/console/configuring-console.asciidoc b/docs/dev-tools/console/configuring-console.asciidoc similarity index 100% rename from docs/console/configuring-console.asciidoc rename to docs/dev-tools/console/configuring-console.asciidoc diff --git a/docs/console.asciidoc b/docs/dev-tools/console/console.asciidoc similarity index 77% rename from docs/console.asciidoc rename to docs/dev-tools/console/console.asciidoc index 25d6876ef27f27..68cf8df25ed14b 100644 --- a/docs/console.asciidoc +++ b/docs/dev-tools/console/console.asciidoc @@ -5,7 +5,7 @@ The Console plugin provides a UI to interact with the REST API of Elasticsearch. where you compose requests to Elasticsearch, and the *response* pane, which displays the responses to the request. .The Console UI -image::images/introduction_screen.png[Screenshot] +image::dev-tools/console/images/introduction_screen.png[Screenshot] Console understands commands in a cURL-like syntax. For example the following Console command @@ -39,7 +39,7 @@ names. [[suggestions]] .API suggestions -image::images/introduction_suggestion.png["Suggestions",width=400,align="center"] +image::dev-tools/console/images/introduction_suggestion.png["Suggestions",width=400,align="center"] Once you have typed a command in to the left pane, you can submit it to Elasticsearch by clicking the little green triangle that appears next to the URL line of the request. Notice that as you move the cursor around, the little @@ -48,12 +48,12 @@ triangle that appears next to the URL line of the request. Notice that as you mo [[action_menu]] .The Action Menu -image::images/introduction_action_menu.png["The Action Menu",width=400,align="center"] +image::dev-tools/console/images/introduction_action_menu.png["The Action Menu",width=400,align="center"] When the response come back, you should see it in the left hand panel: .The Output Pane -image::images/introduction_output.png[Screenshot] +image::dev-tools/console/images/introduction_output.png[Screenshot] [float] [[console-ui]] @@ -63,14 +63,14 @@ In this section you will find a more detailed description of UI of Console. The in the <> section. -include::console/multi-requests.asciidoc[] +include::multi-requests.asciidoc[] -include::console/auto-formatting.asciidoc[] +include::auto-formatting.asciidoc[] -include::console/keyboard-shortcuts.asciidoc[] +include::keyboard-shortcuts.asciidoc[] -include::console/history.asciidoc[] +include::history.asciidoc[] -include::console/settings.asciidoc[] +include::settings.asciidoc[] -include::console/configuring-console.asciidoc[] +include::configuring-console.asciidoc[] diff --git a/docs/console/history.asciidoc b/docs/dev-tools/console/history.asciidoc similarity index 100% rename from docs/console/history.asciidoc rename to docs/dev-tools/console/history.asciidoc diff --git a/docs/images/introduction_action_menu.png b/docs/dev-tools/console/images/introduction_action_menu.png similarity index 100% rename from docs/images/introduction_action_menu.png rename to docs/dev-tools/console/images/introduction_action_menu.png diff --git a/docs/images/introduction_output.png b/docs/dev-tools/console/images/introduction_output.png similarity index 100% rename from docs/images/introduction_output.png rename to docs/dev-tools/console/images/introduction_output.png diff --git a/docs/images/introduction_screen.png b/docs/dev-tools/console/images/introduction_screen.png similarity index 100% rename from docs/images/introduction_screen.png rename to docs/dev-tools/console/images/introduction_screen.png diff --git a/docs/images/introduction_suggestion.png b/docs/dev-tools/console/images/introduction_suggestion.png similarity index 100% rename from docs/images/introduction_suggestion.png rename to docs/dev-tools/console/images/introduction_suggestion.png diff --git a/docs/console/keyboard-shortcuts.asciidoc b/docs/dev-tools/console/keyboard-shortcuts.asciidoc similarity index 100% rename from docs/console/keyboard-shortcuts.asciidoc rename to docs/dev-tools/console/keyboard-shortcuts.asciidoc diff --git a/docs/console/multi-requests.asciidoc b/docs/dev-tools/console/multi-requests.asciidoc similarity index 100% rename from docs/console/multi-requests.asciidoc rename to docs/dev-tools/console/multi-requests.asciidoc diff --git a/docs/console/settings.asciidoc b/docs/dev-tools/console/settings.asciidoc similarity index 100% rename from docs/console/settings.asciidoc rename to docs/dev-tools/console/settings.asciidoc diff --git a/x-pack/docs/en/grokdebugger/getting-started.asciidoc b/docs/dev-tools/grokdebugger/getting-started.asciidoc similarity index 92% rename from x-pack/docs/en/grokdebugger/getting-started.asciidoc rename to docs/dev-tools/grokdebugger/getting-started.asciidoc index 86e82038dd5b69..65aa43a7e1afdd 100644 --- a/x-pack/docs/en/grokdebugger/getting-started.asciidoc +++ b/docs/dev-tools/grokdebugger/getting-started.asciidoc @@ -26,7 +26,7 @@ locally, go to `http://localhost:5601/`. . Click **DevTools** in the side navigation and then click **Grok Debugger** on the top navigation bar. + -image::grokdebugger/images/grok-debugger.png["Grok Debugger UI"] +image::dev-tools/grokdebugger/images/grok-debugger.png["Grok Debugger UI"] . Under Sample Data, enter a sample message that is representative of the data you want to parse. For example: @@ -50,13 +50,13 @@ For example, to parse the log line in the example, you use: Under Structured Data, you'll see the simulated event that results from applying the grok pattern: + -image::grokdebugger/images/grok-debugger-output.png["Viewing Grok Debugger Output"] +image::dev-tools/grokdebugger/images/grok-debugger-output.png["Viewing Grok Debugger Output"] + Any errors in the pattern will appear at the top of the page. For example, here you see a parse exception because the pattern name is misspelled as `WORDD` and therefore can't be found in the pattern dictionary: + -image::grokdebugger/images/grok-debugger-error.png["Viewing Grok Debugger Errors"] +image::dev-tools/grokdebugger/images/grok-debugger-error.png["Viewing Grok Debugger Errors"] + You can click the **More** link to see more detail about the message. + @@ -114,7 +114,7 @@ MSG message-id=<%{GREEDYDATA}> Under Output, you'll see the simulated output event that results from applying the grok pattern that contains the custom pattern: + -image::grokdebugger/images/grok-debugger-custom-pattern.png["Debugging a custom pattern"] +image::dev-tools/grokdebugger/images/grok-debugger-custom-pattern.png["Debugging a custom pattern"] + If an error occurs, you can view the error message and continue iterating over the custom pattern until there are no errors and the output matches the event diff --git a/x-pack/docs/en/grokdebugger/images/grok-debugger-custom-pattern.png b/docs/dev-tools/grokdebugger/images/grok-debugger-custom-pattern.png similarity index 100% rename from x-pack/docs/en/grokdebugger/images/grok-debugger-custom-pattern.png rename to docs/dev-tools/grokdebugger/images/grok-debugger-custom-pattern.png diff --git a/x-pack/docs/en/grokdebugger/images/grok-debugger-error.png b/docs/dev-tools/grokdebugger/images/grok-debugger-error.png similarity index 100% rename from x-pack/docs/en/grokdebugger/images/grok-debugger-error.png rename to docs/dev-tools/grokdebugger/images/grok-debugger-error.png diff --git a/x-pack/docs/en/grokdebugger/images/grok-debugger-output.png b/docs/dev-tools/grokdebugger/images/grok-debugger-output.png similarity index 100% rename from x-pack/docs/en/grokdebugger/images/grok-debugger-output.png rename to docs/dev-tools/grokdebugger/images/grok-debugger-output.png diff --git a/x-pack/docs/en/grokdebugger/images/grok-debugger-overview.png b/docs/dev-tools/grokdebugger/images/grok-debugger-overview.png similarity index 100% rename from x-pack/docs/en/grokdebugger/images/grok-debugger-overview.png rename to docs/dev-tools/grokdebugger/images/grok-debugger-overview.png diff --git a/x-pack/docs/en/grokdebugger/images/grok-debugger-pattern.png b/docs/dev-tools/grokdebugger/images/grok-debugger-pattern.png similarity index 100% rename from x-pack/docs/en/grokdebugger/images/grok-debugger-pattern.png rename to docs/dev-tools/grokdebugger/images/grok-debugger-pattern.png diff --git a/x-pack/docs/en/grokdebugger/images/grok-debugger.png b/docs/dev-tools/grokdebugger/images/grok-debugger.png similarity index 100% rename from x-pack/docs/en/grokdebugger/images/grok-debugger.png rename to docs/dev-tools/grokdebugger/images/grok-debugger.png diff --git a/x-pack/docs/en/grokdebugger/index.asciidoc b/docs/dev-tools/grokdebugger/index.asciidoc similarity index 93% rename from x-pack/docs/en/grokdebugger/index.asciidoc rename to docs/dev-tools/grokdebugger/index.asciidoc index 8dfad0fb3f0297..7eb5843ea6ed7f 100644 --- a/x-pack/docs/en/grokdebugger/index.asciidoc +++ b/docs/dev-tools/grokdebugger/index.asciidoc @@ -20,6 +20,6 @@ ingest node and Logstash share the same grok implementation and pattern libraries, any grok pattern that you create in the Grok Debugger will work in ingest node and Logstash. -image::grokdebugger/images/grok-debugger-overview.png["Grok Debugger"] +image::dev-tools/grokdebugger/images/grok-debugger-overview.png["Grok Debugger"] include::getting-started.asciidoc[] diff --git a/x-pack/docs/en/searchprofiler/getting-started.asciidoc b/docs/dev-tools/searchprofiler/getting-started.asciidoc similarity index 84% rename from x-pack/docs/en/searchprofiler/getting-started.asciidoc rename to docs/dev-tools/searchprofiler/getting-started.asciidoc index a5880c975e7bfb..02fa5014a1a648 100644 --- a/x-pack/docs/en/searchprofiler/getting-started.asciidoc +++ b/docs/dev-tools/searchprofiler/getting-started.asciidoc @@ -21,19 +21,19 @@ locally, go to `http://localhost:5601/`. . Click **DevTools** in the side navigation to open the Search Profiler. Console is the default tool to open when first accessing DevTools. + -image::searchprofiler/images/gs1.png["Opening DevTools"] +image::dev-tools/searchprofiler/images/gs1.png["Opening DevTools"] + On the top navigation bar, click the second item: *Search Profiler* + -image::searchprofiler/images/gs2.png["Opening the Search Profiler"] +image::dev-tools/searchprofiler/images/gs2.png["Opening the Search Profiler"] . This opens the Search Profiler interface. + -image::searchprofiler/images/gs3.png["Search Profiler Interface"] +image::dev-tools/searchprofiler/images/gs3.png["Search Profiler Interface"] . Replace the default `match_all` query with the query you want to profile and click *Profile*. + -image::searchprofiler/images/gs4.png["Profiling the match_all query"] +image::dev-tools/searchprofiler/images/gs4.png["Profiling the match_all query"] + Search Profiler displays the names of the indices searched, the shards in each index, and how long the query took. The following example shows the results of profiling @@ -45,7 +45,7 @@ Cumulative Time that the query took 0.132ms to execute. Of the five shards in th index (`DWZD0iosQNeJMTvb4q1JDw` 0 through 5), shard 3 was the slowest (0.053ms), followed by shard 2 (0.038ms). Shards are sorted by their time in descending order. + -image::searchprofiler/images/gs5.png["Profile details for the test index"] +image::dev-tools/searchprofiler/images/gs5.png["Profile details for the test index"] + [NOTE] ==== @@ -66,7 +66,7 @@ In this example, there is a single `"MatchAllDocsQuery"` that ran on the shard. Since it was the only query run, it took 100% of the time. When you mouse over a row, the Search Profiler displays additional information about the query component." + -image::searchprofiler/images/gs6.png["Profile details for the first shard"] +image::dev-tools/searchprofiler/images/gs6.png["Profile details for the first shard"] + This panel shows the timing breakdown of low-level Lucene methods. For more information, see the reference docs for {ref}/_profiling_queries.html#_timing_breakdown[Timing Breakdown]. diff --git a/x-pack/docs/en/searchprofiler/gs-index.asciidoc b/docs/dev-tools/searchprofiler/gs-index.asciidoc similarity index 85% rename from x-pack/docs/en/searchprofiler/gs-index.asciidoc rename to docs/dev-tools/searchprofiler/gs-index.asciidoc index 913f5137217aea..fcb97795befb6d 100644 --- a/x-pack/docs/en/searchprofiler/gs-index.asciidoc +++ b/docs/dev-tools/searchprofiler/gs-index.asciidoc @@ -12,7 +12,7 @@ into a visualization that is easy to navigate, allowing you to diagnose and debu poorly performing queries much faster. -image::images/overview.png["Search Profiler Visualization"] +image::dev-tools/searchprofile/images/overview.png["Search Profiler Visualization"] -- diff --git a/x-pack/docs/en/searchprofiler/images/filter.png b/docs/dev-tools/searchprofiler/images/filter.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/filter.png rename to docs/dev-tools/searchprofiler/images/filter.png diff --git a/x-pack/docs/en/searchprofiler/images/gs1.png b/docs/dev-tools/searchprofiler/images/gs1.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/gs1.png rename to docs/dev-tools/searchprofiler/images/gs1.png diff --git a/x-pack/docs/en/searchprofiler/images/gs10.png b/docs/dev-tools/searchprofiler/images/gs10.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/gs10.png rename to docs/dev-tools/searchprofiler/images/gs10.png diff --git a/x-pack/docs/en/searchprofiler/images/gs2.png b/docs/dev-tools/searchprofiler/images/gs2.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/gs2.png rename to docs/dev-tools/searchprofiler/images/gs2.png diff --git a/x-pack/docs/en/searchprofiler/images/gs3.png b/docs/dev-tools/searchprofiler/images/gs3.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/gs3.png rename to docs/dev-tools/searchprofiler/images/gs3.png diff --git a/x-pack/docs/en/searchprofiler/images/gs4.png b/docs/dev-tools/searchprofiler/images/gs4.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/gs4.png rename to docs/dev-tools/searchprofiler/images/gs4.png diff --git a/x-pack/docs/en/searchprofiler/images/gs5.png b/docs/dev-tools/searchprofiler/images/gs5.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/gs5.png rename to docs/dev-tools/searchprofiler/images/gs5.png diff --git a/x-pack/docs/en/searchprofiler/images/gs6.png b/docs/dev-tools/searchprofiler/images/gs6.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/gs6.png rename to docs/dev-tools/searchprofiler/images/gs6.png diff --git a/x-pack/docs/en/searchprofiler/images/gs7.png b/docs/dev-tools/searchprofiler/images/gs7.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/gs7.png rename to docs/dev-tools/searchprofiler/images/gs7.png diff --git a/x-pack/docs/en/searchprofiler/images/gs8.png b/docs/dev-tools/searchprofiler/images/gs8.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/gs8.png rename to docs/dev-tools/searchprofiler/images/gs8.png diff --git a/x-pack/docs/en/searchprofiler/images/gs9.png b/docs/dev-tools/searchprofiler/images/gs9.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/gs9.png rename to docs/dev-tools/searchprofiler/images/gs9.png diff --git a/x-pack/docs/en/searchprofiler/images/overview.png b/docs/dev-tools/searchprofiler/images/overview.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/overview.png rename to docs/dev-tools/searchprofiler/images/overview.png diff --git a/x-pack/docs/en/searchprofiler/images/pasting.png b/docs/dev-tools/searchprofiler/images/pasting.png similarity index 100% rename from x-pack/docs/en/searchprofiler/images/pasting.png rename to docs/dev-tools/searchprofiler/images/pasting.png diff --git a/x-pack/docs/en/searchprofiler/index.asciidoc b/docs/dev-tools/searchprofiler/index.asciidoc similarity index 87% rename from x-pack/docs/en/searchprofiler/index.asciidoc rename to docs/dev-tools/searchprofiler/index.asciidoc index 5ef70e066d8fdb..3980b3509ef50a 100644 --- a/x-pack/docs/en/searchprofiler/index.asciidoc +++ b/docs/dev-tools/searchprofiler/index.asciidoc @@ -11,7 +11,7 @@ into a visualization that is easy to navigate, allowing you to diagnose and debu poorly performing queries much faster. -image::searchprofiler/images/overview.png["Search Profiler Visualization"] +image::dev-tools/searchprofiler/images/overview.png["Search Profiler Visualization"] include::getting-started.asciidoc[] diff --git a/x-pack/docs/en/searchprofiler/misc.asciidoc b/docs/dev-tools/searchprofiler/misc.asciidoc similarity index 86% rename from x-pack/docs/en/searchprofiler/misc.asciidoc rename to docs/dev-tools/searchprofiler/misc.asciidoc index a9d3d62a75c419..420d8eb6fe2255 100644 --- a/x-pack/docs/en/searchprofiler/misc.asciidoc +++ b/docs/dev-tools/searchprofiler/misc.asciidoc @@ -11,6 +11,6 @@ and Type filters at the top-left of the UI In the following example, the query is executed against the indices `my_index` and `my_index1` and the type `my_type`: -image::searchprofiler/images/filter.png["Filtering by index and type"] +image::dev-tools/searchprofiler/images/filter.png["Filtering by index and type"] This is equivalent to `GET /my_index,my_index2/my_type/_search`. diff --git a/x-pack/docs/en/searchprofiler/more-complicated.asciidoc b/docs/dev-tools/searchprofiler/more-complicated.asciidoc similarity index 91% rename from x-pack/docs/en/searchprofiler/more-complicated.asciidoc rename to docs/dev-tools/searchprofiler/more-complicated.asciidoc index f51c7659c8b860..e1c5f4bdac4a40 100644 --- a/x-pack/docs/en/searchprofiler/more-complicated.asciidoc +++ b/docs/dev-tools/searchprofiler/more-complicated.asciidoc @@ -29,7 +29,7 @@ POST test/test/_bulk grayed-out `_all`). This restricts profiled queries to the `test` index. + -- -image::searchprofiler/images/gs7.png["Using the index filter"] +image::dev-tools/searchprofiler/images/gs7.png["Using the index filter"] -- . Replace the default `match_all` query with a query that has two sub-query @@ -74,7 +74,7 @@ the following query into the query editor. . Click *Profile* to profile the query and visualize the results. + -- -image::searchprofiler/images/gs8.png["Profiling the more complicated query"] +image::dev-tools/searchprofiler/images/gs8.png["Profiling the more complicated query"] As before, you'll see a list of shards appear in the center panel. You'll notice that the query was slightly slower (15ms vs 0.13ms) because it actually had to do @@ -84,7 +84,7 @@ a bit of work this time, unlike the `match_all` query. . Click the first shard's Expand button to view the query details. + -- -image::searchprofiler/images/gs9.png["Drilling into the first shard's details"] +image::dev-tools/searchprofiler/images/gs9.png["Drilling into the first shard's details"] -- @@ -113,7 +113,7 @@ This particular query also includes a aggregation (a `stats` agg on the `"age"` To view Aggregation profiling statistics, click the *Aggregation Profile* tab. This tab is only enabled if the query being profiled contains an aggregation. -image::searchprofiler/images/gs10.png["Drilling into the first shard's details"] +image::dev-tools/searchprofiler/images/gs10.png["Drilling into the first shard's details"] Click a shard's Expand button to view the aggregation details. Hover over an aggregation row to view the timing breakdown. diff --git a/x-pack/docs/en/searchprofiler/pasting.asciidoc b/docs/dev-tools/searchprofiler/pasting.asciidoc similarity index 98% rename from x-pack/docs/en/searchprofiler/pasting.asciidoc rename to docs/dev-tools/searchprofiler/pasting.asciidoc index 2b24c13f2aa42f..d1280b6a62cd50 100644 --- a/x-pack/docs/en/searchprofiler/pasting.asciidoc +++ b/docs/dev-tools/searchprofiler/pasting.asciidoc @@ -157,4 +157,4 @@ query editor and click *Profile*: -------------------------------------------------- // NOTCONSOLE -image::searchprofiler/images/pasting.png["Visualizing pre-collected responses"] +image::dev-tools/searchprofiler/images/pasting.png["Visualizing pre-collected responses"] diff --git a/docs/development/plugin/development-plugin-resources.asciidoc b/docs/development/plugin/development-plugin-resources.asciidoc index c4a46cde0464f9..ef05fad1b6027b 100644 --- a/docs/development/plugin/development-plugin-resources.asciidoc +++ b/docs/development/plugin/development-plugin-resources.asciidoc @@ -51,4 +51,24 @@ The Kibana directory must be named `kibana`, and your plugin directory must be l If you're developing a plugin that has a user interface, take a look at our https://elastic.github.io/eui[Elastic UI Framework]. It documents the CSS and React components we use to build Kibana's user interface. -You're welcome to use these components, but be aware that they are rapidly evolving and we might introduce breaking changes that will disrupt your plugin's UI. \ No newline at end of file +You're welcome to use these components, but be aware that they are rapidly evolving and we might introduce breaking changes that will disrupt your plugin's UI. + +[float] +==== TypeScript Support +Plugin code can be written in http://www.typescriptlang.org/[TypeScript] if desired. To enable TypeScript support create a `tsconfig.json` file at the root of your plugin that looks something like this: + +["source","js"] +----------- +{ + // extend Kibana's tsconfig, or use your own settings + "extends": "../../kibana/tsconfig.json", + + // tell the TypeScript compiler where to find your source files + "include": [ + "server/**/*", + "public/**/*" + ] +} +----------- + +TypeScript code is automatically converted into JavaScript during development, but not in the distributable version of Kibana. If you use the {repo}blob/{branch}/packages/kbn-plugin-helpers[@kbn/plugin-helpers] to build your plugin then your `.ts` and `.tsx` files will be permanently transpiled before your plugin is archived. If you have your own build process, make sure to run the TypeScript compiler on your source files and ship the compilation output so that your plugin will work with the distributable version of Kibana. diff --git a/docs/discover/context.asciidoc b/docs/discover/context.asciidoc index 2492222ae132f6..2c85358f84d52a 100644 --- a/docs/discover/context.asciidoc +++ b/docs/discover/context.asciidoc @@ -32,7 +32,7 @@ pattern the context is based on. While not required, it is recommended to only use fields which have {ref}/doc-values.html[doc values] enabled to achieve -good performance and avoid unnecessary {ref}/modules-fielddata.html[field +good performance and avoid unnecessary {ref}/modules-fielddata.html[field data] usage. Common examples for suitable fields include log line numbers, monotonically increasing counters and high-precision timestamps. -- @@ -43,6 +43,8 @@ NOTE: The number of documents displayed by default can be configured via the `context:defaultSize` setting in < Advanced Settings*>>. +[float] +[[change-context-size]] === Changing the Context Size You can change the number documents displayed before and after the anchor @@ -66,6 +68,8 @@ NOTE: The default number of documents loaded with each button click can be configured via the `context:step` setting in < Advanced Settings*>>. +[float] +[[filter-context]] === Filtering the Context Depending on how the documents are partitioned into index patterns, the context diff --git a/docs/discover/viewing-field-stats.asciidoc b/docs/discover/viewing-field-stats.asciidoc index f4a87d526003c7..d9fd3b9eb033b4 100644 --- a/docs/discover/viewing-field-stats.asciidoc +++ b/docs/discover/viewing-field-stats.asciidoc @@ -5,6 +5,10 @@ From the Fields list, you can see how many of the documents in the Documents table contain a particular field, what the top 5 values are, and what percentage of documents contain each value. +Data can be visualized in various ways. The quick visualize can only be +applied to aggregatable fields. The keyword fields can be visualized and +they are available in the side bar if we uncheck "Hide missing fields". + To view field data statistics, click the name of a field in the Fields list. image:images/filter-field.jpg[Field Statistics] \ No newline at end of file diff --git a/docs/getting-started.asciidoc b/docs/getting-started.asciidoc index 582578600b6c6f..2ecefe49821b9c 100644 --- a/docs/getting-started.asciidoc +++ b/docs/getting-started.asciidoc @@ -3,24 +3,21 @@ [partintro] -- -Ready to get some hands-on experience with Kibana? +Ready to get some hands-on experience with Kibana? This tutorial shows you how to: * Load a sample data set into Elasticsearch * Define an index pattern -* Explore the sample data with {kibana-ref}/discover.html[Discover] -* Set up {kibana-ref}/visualize.html[_visualizations_] of the sample data -* Assemble visualizations into a {kibana-ref}/dashboard.html[Dashboard] +* Discover and explore the sample data +* Visualize the data +* Assemble visualizations into a dashboard Before you begin, make sure you've <> and established a {kibana-ref}/connect-to-elasticsearch.html[connection to Elasticsearch]. -You might also be interested in these video tutorials: - -* https://www.elastic.co/blog/kibana-4-video-tutorials-part-1[High-level Kibana introduction, pie charts] -* https://www.elastic.co/blog/kibana-4-video-tutorials-part-2[Data discovery, bar charts, and line charts] -* https://www.elastic.co/blog/kibana-4-video-tutorials-part-3[Coordinate maps] -* https://www.elastic.co/blog/kibana-4-video-tutorials-part-4[Embedding Kibana visualizations] +You might also be interested in the +https://www.elastic.co/webinars/getting-started-kibana[Getting Started with Kibana] +video tutorial. -- include::getting-started/tutorial-load-dataset.asciidoc[] diff --git a/docs/getting-started/tutorial-dashboard.asciidoc b/docs/getting-started/tutorial-dashboard.asciidoc index bb4de2157ef01b..42e7885b222d43 100644 --- a/docs/getting-started/tutorial-dashboard.asciidoc +++ b/docs/getting-started/tutorial-dashboard.asciidoc @@ -1,20 +1,27 @@ [[tutorial-dashboard]] -== Putting it all Together with Dashboards +== Putting it Together in a Dashboard -A dashboard is a collection of visualizations that you can arrange and share. -To build a dashboard that contains the visualizations you saved during this tutorial: +A dashboard is a collection of visualizations that you can arrange and share. +Here you'll build a dashboard that contains the visualizations you saved during +this tutorial. -. Click *Dashboard* in the side navigation. -. Click *Add* to display the list of saved visualizations. -. Click _Markdown Example_, _Pie Example_, _Bar Example_, and _Map Example_, then close the list of -visualizations by clicking the small up-arrow at the bottom of the list. +. Open *Dashboard*. +. Click *Create new dashboard*. +. Click *Add*. +. Click *Bar Example*, *Map Example*, *Markdown Example*, and *Pie Example*. -Hovering over a visualization displays the container controls that enable you to -edit, move, delete, and resize the visualization. -Your sample dashboard should end up looking roughly like this: +Your sample dashboard look like this: +[role="screenshot"] image::images/tutorial-dashboard.png[] +You can rearrange the visualizations by clicking a the header of a +visualization and dragging. The gear icon in the top right of a visualization +displays controls for editing and deleting the visualization. A resize control +is on the lower right. + To get a link to share or HTML code to embed the dashboard in a web page, save the dashboard and click *Share*. + +*Save* your dashboard. diff --git a/docs/getting-started/tutorial-define-index.asciidoc b/docs/getting-started/tutorial-define-index.asciidoc index df84b2fc25e600..62ce2fc9511df3 100644 --- a/docs/getting-started/tutorial-define-index.asciidoc +++ b/docs/getting-started/tutorial-define-index.asciidoc @@ -1,22 +1,45 @@ [[tutorial-define-index]] == Defining Your Index Patterns -Each set of data loaded to Elasticsearch has an index pattern. In the previous section, the -Shakespeare data set has an index named `shakespeare`, and the accounts data set has an index named `bank`. An _index -pattern_ is a string with optional wildcards that can match multiple indices. For example, in the common logging use -case, a typical index name contains the date in YYYY.MM.DD format, and an index pattern for May would look something -like `logstash-2015.05*`. - -For this tutorial, any pattern that matches the name of an index we've loaded will work. Open a browser and -navigate to `localhost:5601`. Click the *Management* tab, then the *Index Patterns* tab. Click *Add New* to define a new index -pattern. Two of the sample data sets, the Shakespeare plays and the financial accounts, don't contain time-series data. -Make sure the *Index contains time-based events* box is unchecked when you create index patterns for these data sets. -Specify `shakes*` as the index pattern for the Shakespeare data set and click *Create* to define the index pattern, then -define a second index pattern named `ba*`. - -The Logstash data set does contain time-series data, so after clicking *Add New* to define the index for this data -set, make sure the *Index contains time-based events* box is checked and select the `@timestamp` field from the -*Time-field name* drop-down. - -NOTE: When you define an index pattern, indices that match that pattern must exist in Elasticsearch. Those indices must -contain data. You can check what indices exist by using `GET _cat/indices` in <>, under Dev Tools, or `curl -XGET "http://localhost:9200/_cat/indices"`. +Index patterns tell Kibana which Elasticsearch indices you want to explore. +An index pattern can match the name of a single index, or include a wildcard +(*) to match multiple indices. + +For example, Logstash typically creates a +series of indices in the format `logstash-YYYY.MMM.DD`. To explore all +of the log data from May 2018, you could specify the index pattern +`logstash-2018.05*`. + +Create patterns for the Shakespeare data set, which has an +index named `shakespeare,` and the accounts data set, which has an index named +`bank.` These data sets don't contain time-series data. + +. In Kibana, open *Management*, and then click *Index Patterns.* +. If this is your first index pattern, the *Create index pattern* page opens automatically. +Otherwise, click *Create index pattern* in the upper left. +. Enter `shakes*` in the *Index pattern* field. ++ +[role="screenshot"] +image::images/tutorial-pattern-1.png[] + +. Click *Next step*. +. In *Configure settings*, click *Create index pattern*. For this pattern, +you don't need to configure any settings. +. Define a second index pattern named `ba*` You don't need to configure any settings for this pattern. + +Now create an index pattern for the Logstash data set. This data set +contains time-series data. + +. Define an index pattern named `logstash*.` +. Click *Next step*. +. In *Configure settings*, select *@timestamp* in the *Time Filter field name* dropdown menu. +. Click *Create index pattern*. + + + + +NOTE: When you define an index pattern, the indices that match that pattern must +exist in Elasticsearch and they must contain data. To check which indices are +available, go to *Dev Tools > Console* and enter `GET _cat/indices`. Alternately, use +`curl -XGET "http://localhost:9200/_cat/indices"`. + diff --git a/docs/getting-started/tutorial-discovering.asciidoc b/docs/getting-started/tutorial-discovering.asciidoc index a0d7655f00dfde..623c2a4d027198 100644 --- a/docs/getting-started/tutorial-discovering.asciidoc +++ b/docs/getting-started/tutorial-discovering.asciidoc @@ -1,42 +1,29 @@ [[tutorial-discovering]] == Discovering Your Data -Click *Discover* in the side navigation to display Kibana's data discovery functions: - -image::images/tutorial-discover.png[] - -In the query bar, you can enter an -{ref}/query-dsl-query-string-query.html#query-string-syntax[Elasticsearch -query] to search your data. You can explore the results in Discover and create -visualizations of saved searches in Visualize. - -The current index pattern is displayed beneath the query bar. The index pattern -determines which indices are searched when you submit a query. To search a -different set of indices, select different pattern from the drop down menu. -To add an index pattern, go to *Management/Kibana/Index Patterns* and click -*Add New*. - -You can construct searches by using the field names and the values you're -interested in. With numeric fields you can use comparison operators such as -greater than (>), less than (<), or equals (=). You can link elements with the -logical operators AND, OR, and NOT, all in uppercase. - -To try it out, select the `ba*` index pattern and enter the following query string -in the query bar: - +Using the Discover application, you can enter +an {ref}/query-dsl-query-string-query.html#query-string-syntax[Elasticsearch +query] to search your data and filter the results. + +. Open *Discover*. The `shakes*` pattern is the current index pattern. +. Click the caret to the right of `shakes*`, and select `ba*`. +. In the search field, enter the following string: ++ [source,text] account_number:<100 AND balance:>47500 -This query returns all account numbers between zero and 99 with balances in -excess of 47,500. When searching the sample bank data, it returns 5 results: -Account numbers 8, 32, 78, 85, and 97. +The search returns all account numbers between zero and 99 with balances in +excess of 47,500. It returns results for account numbers 8, 32, 78, 85, and 97. +[role="screenshot"] image::images/tutorial-discover-2.png[] By default, all fields are shown for each matching document. To choose which -document fields to display, hover over the Available Fields list and click the -*add* button next to each field you want include. For example, if you add -just the `account_number`, the display changes to a simple list of five -account numbers: +fields to display, hover the mouse over the the list of *Available Fields* +and then click *add* next to each field you want include. + +For example, if you add the `account_number` field, the display changes to a list of five +account numbers. +[role="screenshot"] image::images/tutorial-discover-3.png[] diff --git a/docs/getting-started/tutorial-load-dataset.asciidoc b/docs/getting-started/tutorial-load-dataset.asciidoc index 61b05c0b19e9f5..de605f6a7143c3 100644 --- a/docs/getting-started/tutorial-load-dataset.asciidoc +++ b/docs/getting-started/tutorial-load-dataset.asciidoc @@ -1,22 +1,22 @@ [[tutorial-load-dataset]] == Loading Sample Data -The tutorials in this section rely on the following data sets: +This tutorial requires three data sets: -* The complete works of William Shakespeare, suitably parsed into fields. Download this data set by clicking here: - https://download.elastic.co/demos/kibana/gettingstarted/shakespeare_6.0.json[shakespeare.json]. -* A set of fictitious accounts with randomly generated data. Download this data set by clicking here: - https://download.elastic.co/demos/kibana/gettingstarted/accounts.zip[accounts.zip] -* A set of randomly generated log files. Download this data set by clicking here: - https://download.elastic.co/demos/kibana/gettingstarted/logs.jsonl.gz[logs.jsonl.gz] +* The complete works of William Shakespeare, suitably parsed into fields. Download + https://download.elastic.co/demos/kibana/gettingstarted/shakespeare_6.0.json[`shakespeare.json`]. +* A set of fictitious accounts with randomly generated data. Download + https://download.elastic.co/demos/kibana/gettingstarted/accounts.zip[`accounts.zip`]. +* A set of randomly generated log files. Download + https://download.elastic.co/demos/kibana/gettingstarted/logs.jsonl.gz[`logs.jsonl.gz`]. -Two of the data sets are compressed. Use the following commands to extract the files: +Two of the data sets are compressed. To extract the files, use these commands: [source,shell] unzip accounts.zip gunzip logs.jsonl.gz -The Shakespeare data set is organized in the following schema: +The Shakespeare data set has this structure: [source,json] { @@ -28,7 +28,7 @@ The Shakespeare data set is organized in the following schema: "text_entry": "String", } -The accounts data set is organized in the following schema: +The accounts data set is structured as follows: [source,json] { @@ -45,7 +45,7 @@ The accounts data set is organized in the following schema: "state": "String" } -The schema for the logs data set has dozens of different fields, but the notable ones used in this tutorial are: +The logs data set has dozens of different fields. Here are the notable fields for this tutorial: [source,json] { @@ -54,11 +54,12 @@ The schema for the logs data set has dozens of different fields, but the notable "@timestamp": "date" } -Before we load the Shakespeare and logs data sets, we need to set up {ref}/mapping.html[_mappings_] for the fields. -Mapping divides the documents in the index into logical groups and specifies a field's characteristics, such as the -field's searchability or whether or not it's _tokenized_, or broken up into separate words. +Before you load the Shakespeare and logs data sets, you must set up {ref}/mapping.html[_mappings_] for the fields. +Mappings divide the documents in the index into logical groups and specify the characteristics +of the fields. These characteristics include the searchability of the field +and whether it's _tokenized_, or broken up into separate words. -Use the following command in the Kibana Console to set up a mapping for the Shakespeare data set: +In Kibana *Dev Tools > Console*, set up a mapping for the Shakespeare data set: [source,js] PUT /shakespeare @@ -77,15 +78,14 @@ PUT /shakespeare //CONSOLE -This mapping specifies the following qualities for the data set: +This mapping specifies field characteristics for the data set: -* Because the _speaker_ and _play_name_ fields are keyword fields, they are not analyzed. The strings are treated as a single unit even if they contain multiple words. -* The _line_id_ and _speech_number_ fields are integers. +* The `speaker` and `play_name` fields are keyword fields. These fields are not analyzed. +The strings are treated as a single unit even if they contain multiple words. +* The `line_id` and `speech_number` fields are integers. -The logs data set requires a mapping to label the latitude/longitude pairs in the logs as geographic locations by -applying the `geo_point` type to those fields. - -Use the following commands to establish `geo_point` mapping for the logs: +The logs data set requires a mapping to label the latitude and longitude pairs +as geographic locations by applying the `geo_point` type. [source,js] PUT /logstash-2015.05.18 @@ -147,8 +147,10 @@ PUT /logstash-2015.05.20 //CONSOLE -The accounts data set doesn't require any mappings, so at this point we're ready to use the Elasticsearch -{ref}/docs-bulk.html[`bulk`] API to load the data sets with the following commands: +The accounts data set doesn't require any mappings. + +At this point, you're ready to use the Elasticsearch {ref}/docs-bulk.html[bulk] +API to load the data sets: [source,shell] curl -H 'Content-Type: application/x-ndjson' -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json @@ -161,16 +163,16 @@ Invoke-RestMethod "http://localhost:9200/bank/account/_bulk?pretty" -Method Post Invoke-RestMethod "http://localhost:9200/shakespeare/doc/_bulk?pretty" -Method Post -ContentType 'application/x-ndjson' -InFile "shakespeare_6.0.json" Invoke-RestMethod "http://localhost:9200/_bulk?pretty" -Method Post -ContentType 'application/x-ndjson' -InFile "logs.jsonl" -These commands may take some time to execute, depending on the computing resources available. +These commands might take some time to execute, depending on the available computing resources. -Verify successful loading with the following command: +Verify successful loading: [source,js] GET /_cat/indices?v //CONSOLE -You should see output similar to the following: +Your output should look similar to this: [source,shell] health status index pri rep docs.count docs.deleted store.size pri.store.size diff --git a/docs/getting-started/tutorial-visualizing.asciidoc b/docs/getting-started/tutorial-visualizing.asciidoc index 6d3e273c563726..6067ac8a8130a4 100644 --- a/docs/getting-started/tutorial-visualizing.asciidoc +++ b/docs/getting-started/tutorial-visualizing.asciidoc @@ -1,46 +1,45 @@ [[tutorial-visualizing]] == Visualizing Your Data -To start visualizing your data, click *Visualize* in the side navigation. - -The *Visualize* tools enable you to view your data in several ways. For example, -let's use that venerable visualization, the pie chart, to get some insight -into the account balances in the sample bank account data. To get started, click the big blue -**Create a visualization** button in the center of the screen. - -image::images/tutorial-visualize-landing.png[] - -There are a number of visualization types to choose from. Let's click the one -called *Pie*. +In the Visualize application, you can shape your data using a variety +of charts, tables, and maps, and more. You'll create four +visualizations: a pie chart, bar chart, coordinate map, and Markdown widget. +. Open *Visualize.* +. Click *Create a visualization* or the *+* button. You'll see all the visualization +types in Kibana. ++ +[role="screenshot"] image::images/tutorial-visualize-wizard-step-1.png[] +. Click *Pie*. -You can build visualizations from saved searches, or enter new search criteria. To enter -new search criteria, you first need to select an index pattern to specify -what indices to search. We want to search the account data, so select the `ba*` -index pattern. - +. In *New Search*, select the `ba*` index pattern. You'll use the pie chart to +gain insight into the account balances in the bank account data. ++ +[role="screenshot"] image::images/tutorial-visualize-wizard-step-2.png[] -The default search matches all documents. Initially, a single "slice" -encompasses the entire pie: +=== Pie Chart +Initially, the pie contains a single "slice." +That's because the default search matched all documents. + +[role="screenshot"] image::images/tutorial-visualize-pie-1.png[] -To specify what slices to display in the chart, you use an Elasticsearch -{ref}/search-aggregations.html[bucket aggregation]. A bucket aggregation -simply sorts the documents that match your search criteria into different -categories, aka _buckets_. For example, the account data includes the balance -of each account. Using a bucket aggregation, you can establish multiple ranges -of account balances and find out how many accounts fall into each range. +To specify which slices to display in the pie, you use an Elasticsearch +{ref}/search-aggregations.html[bucket aggregation]. This aggregation +sorts the documents that match your search criteria into different +categories, also known as _buckets_. -To define a bucket for each range: +Use a bucket aggregation to establish +multiple ranges of account balances and find out how many accounts fall into +each range. -. Click the *Split Slices* buckets type. -. Select *Range* from the *Aggregation* list. -. Select the *balance* field from the *Field* list. -. Click *Add Range* four times to bring the -total number of ranges to six. +. In the *Buckets* pane, click *Split Slices.* +. In the *Aggregation* dropdown menu, select *Range*. +. In the *Field* dropdown menu, select *balance*. +. Click *Add Range* four times to bring the total number of ranges to six. . Define the following ranges: + [source,text] @@ -51,142 +50,165 @@ total number of ranges to six. 15000 30999 31000 50000 -. Click *Apply changes* image:images/apply-changes-button.png[] to update the chart. +. Click *Apply changes* image:images/apply-changes-button.png[]. Now you can see what proportion of the 1000 accounts fall into each balance range. +[role="screenshot"] image::images/tutorial-visualize-pie-2.png[] -Let's take a look at another dimension of the data: the account holder's -age. By adding another bucket aggregation, you can see the ages of the account -holders in each balance range: +Add another bucket aggregation that looks at the ages of the account +holders. -. Click *Add sub-buckets* below the buckets list. -. Click *Split Slices* in the buckets type list. -. Select *Terms* from the aggregation list. -. Select *age* from the field list. +. At the bottom of the *Buckets* pane, click *Add sub-buckets*. +. In *Select buckets type,* click *Split Slices*. +. In the *Sub Aggregation* dropdown, select *Terms*. +. In the *Field* dropdown, select *age*. . Click *Apply changes* image:images/apply-changes-button.png[]. -Now you can see the break down of the account holders' ages displayed +Now you can see the break down of the ages of the account holders, displayed in a ring around the balance ranges. +[role="screenshot"] image::images/tutorial-visualize-pie-3.png[] -To save this chart so we can use it later, click *Save* and enter the name _Pie Example_. +To save this chart so you can use it later, click *Save* in the top menu bar +and enter `Pie Example`. -Next, we're going to look at data in the Shakespeare data set. Let's find out how the -plays compare when it comes to the number of speaking parts and display the information -in a bar chart: +=== Bar Chart -. Click *New* and select *Vertical bar chart*. -. Select the `shakes*` index pattern. Since you haven't defined any buckets yet, -you'll see a single big bar that shows the total count of documents that match -the default wildcard query. -+ +You'll use a bar chart to look at the Shakespeare data set and compare +the number of speaking parts in the plays. + +Create a *Vertical Bar* chart and set the search source to `shakes*`. +Initially, the chart is a single bar that shows the total count +of documents that match the default wildcard query. + +[role="screenshot"] image::images/tutorial-visualize-bar-1.png[] -. To show the number of speaking parts per play along the y-axis, you need to -configure the Y-axis {ref}/search-aggregations.html[metric aggregation]. A metric -aggregation computes metrics based on values extracted from the search results. -To get the number of speaking parts per play, select the *Unique Count* -aggregation and choose *speaker* from the field list. You can also give the -axis a custom label, _Speaking Parts_. +Show the number of speaking parts per play along the Y-axis. +This requires you to configure the Y-axis +{ref}/search-aggregations.html[metric aggregation.] +This aggregation computes metrics based on values from the search results. + +. In the *Metrics* pane, expand *Y-Axis*. +. Set *Aggregation* to *Unique Count*. +. Set *Field* to *speaker*. +. In the *Custom Label* box, enter `Speaking Parts`. +. Click *Apply changes* image:images/apply-changes-button.png[]. -. To show the different plays long the x-axis, select the X-Axis buckets type, -select *Terms* from the aggregation list, and choose *play_name* from the field -list. To list them alphabetically, select *Ascending* order. You can also give -the axis a custom label, _Play Name_. -. Click *Apply changes* image:images/apply-changes-button.png[] to view the -results. +[role="screenshot"] +image::images/tutorial-visualize-bar-1.5.png[] -image::images/tutorial-visualize-bar-2.png[] -Notice how the individual play names show up as whole phrases, instead of being broken down into individual words. This -is the result of the mapping we did at the beginning of the tutorial, when we marked the *play_name* field as 'not -analyzed'. +Show the plays along the X-axis. + +. In the *Buckets* pane, click *X-Axis*. +. Set *Aggregation* to *Terms* and *Field* to *play_name*. +. To list plays alphabetically, in the *Order* dropdown menu, select *Ascending*. +. Give the axis a custom label, `Play Name`. +. Click *Apply changes* image:images/apply-changes-button.png[]. + +[role="screenshot"] +image::images/0[] -Hovering over each bar shows you the number of speaking parts for each play as a tooltip. To turn tooltips -off and configure other options for your visualizations, select the Visualization builder's *Options* tab. +Hovering over a bar shows a tooltip with the number of speaking parts for +that play. -Now that you have a list of the smallest casts for Shakespeare plays, you might also be curious to see which of these -plays makes the greatest demands on an individual actor by showing the maximum number of speeches for a given part. +Notice how the individual play names show up as whole phrases, instead of +broken into individual words. This is the result of the mapping +you did at the beginning of the tutorial, when your marked the `play_name` field +as `not analyzed`. + + +//// +You might +also be curious to see which plays make the greatest demands on an +individual actor. Let's show the maximum number of speeches for a given part. . Click *Add metrics* to add a Y-axis aggregation. -. Choose the *Max* aggregation and select the *speech_number* field. -. Click *Options* and change the *Bar Mode* from *stacked* to *normal*. -. Click *Apply changes* image:images/apply-changes-button.png[]. Your chart should now look like this: +. Set *Aggregation* to `Max` and *Field* to `speech_number`. +. Click *Metrics & Axes* and then change *Mode* from `stacked` to `normal`. +. Click *Apply changes* image:images/apply-changes-button.png[]. +[role="screenshot"] image::images/tutorial-visualize-bar-3.png[] -As you can see, _Love's Labours Lost_ has an unusually high maximum speech number, compared to the other plays, and -might therefore make more demands on an actor's memory. +The play Love's Labours Lost has an unusually high maximum speech number compared to the other plays. Note how the *Number of speaking parts* Y-axis starts at zero, but the bars don't begin to differentiate until 18. To make the differences stand out, starting the Y-axis at a value closer to the minimum, go to Options and select *Scale Y-Axis to data bounds*. +//// +*Save* this chart with the name `Bar Example`. -Save this chart with the name _Bar Example_. +=== Coordinate Map -Next, we're going to use a coordinate map chart to visualize geographic information in our log file sample data. +Using a coordinate map, you can visualize geographic information in the log file sample data. -. Click *New*. -. Select *Coordinate map*. -. Select the `logstash-*` index pattern. -. Set the time window for the events we're exploring: -. Click the time picker in the Kibana toolbar. +. Create a *Coordinate map* and set the search source to `logstash*`. +. In the top menu bar, click the time picker on the far right. . Click *Absolute*. . Set the start time to May 18, 2015 and the end time to May 20, 2015. -+ -image::images/tutorial-timepicker.png[] +. Click *Go*. -. Once you've got the time range set up, click the *Go* button and close the time picker by -clicking the small up arrow in the bottom right corner. - -You'll see a map of the world, since we haven't defined any buckets yet: +You haven't defined any buckets yet, so the visualization is a map of the world. +[role="screenshot"] image::images/tutorial-visualize-map-1.png[] -To map the geo coordinates from the log files select *Geo Coordinates* as -the bucket and click *Apply changes* image:images/apply-changes-button.png[]. -Your chart should now look like this: +Now map the geo coordinates from the log files. + +. In the *Buckets* pane, click *Geo Coordinates*. +. Set *Aggregation* to *Geohash* and *Field* to *geo.coordinates*. +. Click *Apply changes* image:images/apply-changes-button.png[]. + +The map now looks like this: +[role="screenshot"] image::images/tutorial-visualize-map-2.png[] -You can navigate the map by clicking and dragging, zoom with the -image:images/viz-zoom.png[] buttons, or hit the *Fit Data Bounds* +You can navigate the map by clicking and dragging. The controls +on the top left of the map enable you to zoom the map and set filters. +Give them a try. + +//// +- Zoom image:images/viz-zoom.png[] buttons, +- *Fit Data Bounds* image:images/viz-fit-bounds.png[] button to zoom to the lowest level that -includes all the points. You can also include or exclude a rectangular area +includes all the points. +- Include or exclude a rectangular area by clicking the *Latitude/Longitude Filter* image:images/viz-lat-long-filter.png[] button and drawing a bounding box on the map. Applied filters are displayed below the query bar. Hovering over a filter displays controls to toggle, pin, invert, or delete the filter. +//// +[role="screenshot"] image::images/tutorial-visualize-map-3.png[] -Save this map with the name _Map Example_. +*Save* this map with the name `Map Example`. + +=== Markdown -Finally, create a Markdown widget to display extra information: +The final visualization is a Markdown widget that renders formatted text. -. Click *New*. -. Select *Markdown widget*. -. Enter the following text in the field: +. Create a *Markdown* visualization. +. In the text box, enter the following: + [source,markdown] # This is a tutorial dashboard! The Markdown widget uses **markdown** syntax. > Blockquotes in Markdown use the > character. -. Click *Apply changes* image:images/apply-changes-button.png[] render the Markdown in the -preview pane. -+ -image::images/tutorial-visualize-md-1.png[] - - - +. Click *Apply changes* image:images/apply-changes-button.png[]. +The Markdown renders in the preview pane: +[role="screenshot"] image::images/tutorial-visualize-md-2.png[] -Save this visualization with the name _Markdown Example_. +*Save* this visualization with the name `Markdown Example`. diff --git a/docs/getting-started/wrapping-up.asciidoc b/docs/getting-started/wrapping-up.asciidoc index 6ba43345899c1a..c9c84a6dc81886 100644 --- a/docs/getting-started/wrapping-up.asciidoc +++ b/docs/getting-started/wrapping-up.asciidoc @@ -4,11 +4,11 @@ Now that you have a handle on the basics, you're ready to start exploring your own data with Kibana. -* See {kibana-ref}/discover.html[Discover] for more information about searching and filtering +* See {kibana-ref}/discover.html[Discover] for information about searching and filtering your data. -* See {kibana-ref}/visualize.html[Visualize] for information about all of the visualization +* See {kibana-ref}/visualize.html[Visualize] for information about the visualization types Kibana has to offer. * See {kibana-ref}/management.html[Management] for information about configuring Kibana -and managing your saved objects. -* See {kibana-ref}/console-kibana.html[Console] for information about the interactive -console UI you can use to submit REST requests to Elasticsearch. +and managing your saved objects. +* See {kibana-ref}/console-kibana.html[Console] to learn about the interactive +console you can use to submit REST requests to Elasticsearch. diff --git a/x-pack/docs/en/graph/configuring-graph.asciidoc b/docs/graph/configuring-graph.asciidoc similarity index 100% rename from x-pack/docs/en/graph/configuring-graph.asciidoc rename to docs/graph/configuring-graph.asciidoc diff --git a/x-pack/docs/en/graph/getting-started.asciidoc b/docs/graph/getting-started.asciidoc similarity index 100% rename from x-pack/docs/en/graph/getting-started.asciidoc rename to docs/graph/getting-started.asciidoc diff --git a/x-pack/docs/en/graph/gs-index.asciidoc b/docs/graph/gs-index.asciidoc similarity index 100% rename from x-pack/docs/en/graph/gs-index.asciidoc rename to docs/graph/gs-index.asciidoc diff --git a/x-pack/docs/en/graph/images/connection.jpg b/docs/graph/images/connection.jpg similarity index 100% rename from x-pack/docs/en/graph/images/connection.jpg rename to docs/graph/images/connection.jpg diff --git a/x-pack/docs/en/graph/images/graph-add-query.jpg b/docs/graph/images/graph-add-query.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-add-query.jpg rename to docs/graph/images/graph-add-query.jpg diff --git a/x-pack/docs/en/graph/images/graph-advanced-button.jpg b/docs/graph/images/graph-advanced-button.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-advanced-button.jpg rename to docs/graph/images/graph-advanced-button.jpg diff --git a/x-pack/docs/en/graph/images/graph-expand-button.jpg b/docs/graph/images/graph-expand-button.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-expand-button.jpg rename to docs/graph/images/graph-expand-button.jpg diff --git a/x-pack/docs/en/graph/images/graph-init-screen.jpg b/docs/graph/images/graph-init-screen.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-init-screen.jpg rename to docs/graph/images/graph-init-screen.jpg diff --git a/x-pack/docs/en/graph/images/graph-link-button.jpg b/docs/graph/images/graph-link-button.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-link-button.jpg rename to docs/graph/images/graph-link-button.jpg diff --git a/x-pack/docs/en/graph/images/graph-link-summary.jpg b/docs/graph/images/graph-link-summary.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-link-summary.jpg rename to docs/graph/images/graph-link-summary.jpg diff --git a/x-pack/docs/en/graph/images/graph-network.jpg b/docs/graph/images/graph-network.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-network.jpg rename to docs/graph/images/graph-network.jpg diff --git a/x-pack/docs/en/graph/images/graph-open.jpg b/docs/graph/images/graph-open.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-open.jpg rename to docs/graph/images/graph-open.jpg diff --git a/x-pack/docs/en/graph/images/graph-undo-button.jpg b/docs/graph/images/graph-undo-button.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-undo-button.jpg rename to docs/graph/images/graph-undo-button.jpg diff --git a/x-pack/docs/en/graph/images/graph-url-connections.jpg b/docs/graph/images/graph-url-connections.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-url-connections.jpg rename to docs/graph/images/graph-url-connections.jpg diff --git a/x-pack/docs/en/graph/images/graph-vertices-connections.jpg b/docs/graph/images/graph-vertices-connections.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph-vertices-connections.jpg rename to docs/graph/images/graph-vertices-connections.jpg diff --git a/x-pack/docs/en/graph/images/graph.jpg b/docs/graph/images/graph.jpg similarity index 100% rename from x-pack/docs/en/graph/images/graph.jpg rename to docs/graph/images/graph.jpg diff --git a/x-pack/docs/en/graph/images/midiclicks.jpg b/docs/graph/images/midiclicks.jpg similarity index 100% rename from x-pack/docs/en/graph/images/midiclicks.jpg rename to docs/graph/images/midiclicks.jpg diff --git a/x-pack/docs/en/graph/images/spy.jpg b/docs/graph/images/spy.jpg similarity index 100% rename from x-pack/docs/en/graph/images/spy.jpg rename to docs/graph/images/spy.jpg diff --git a/x-pack/docs/en/graph/index.asciidoc b/docs/graph/index.asciidoc similarity index 100% rename from x-pack/docs/en/graph/index.asciidoc rename to docs/graph/index.asciidoc diff --git a/x-pack/docs/en/graph/introduction.asciidoc b/docs/graph/introduction.asciidoc similarity index 100% rename from x-pack/docs/en/graph/introduction.asciidoc rename to docs/graph/introduction.asciidoc diff --git a/x-pack/docs/en/graph/limitations.asciidoc b/docs/graph/limitations.asciidoc similarity index 100% rename from x-pack/docs/en/graph/limitations.asciidoc rename to docs/graph/limitations.asciidoc diff --git a/x-pack/docs/en/graph/troubleshooting.asciidoc b/docs/graph/troubleshooting.asciidoc similarity index 100% rename from x-pack/docs/en/graph/troubleshooting.asciidoc rename to docs/graph/troubleshooting.asciidoc diff --git a/docs/images/Dashboard-Edit-Mode.png b/docs/images/Dashboard-Edit-Mode.png deleted file mode 100644 index bbaffca323583f..00000000000000 Binary files a/docs/images/Dashboard-Edit-Mode.png and /dev/null differ diff --git a/docs/images/Dashboard-Landing-Page.png b/docs/images/Dashboard-Landing-Page.png deleted file mode 100644 index 46c7825943de5f..00000000000000 Binary files a/docs/images/Dashboard-Landing-Page.png and /dev/null differ diff --git a/docs/images/Dashboard-Tutorial-Edit-Mode.png b/docs/images/Dashboard-Tutorial-Edit-Mode.png deleted file mode 100644 index d1b8480bce9f69..00000000000000 Binary files a/docs/images/Dashboard-Tutorial-Edit-Mode.png and /dev/null differ diff --git a/docs/images/Dashboard-View-Mode.png b/docs/images/Dashboard-View-Mode.png deleted file mode 100644 index d4ddce23f0342e..00000000000000 Binary files a/docs/images/Dashboard-View-Mode.png and /dev/null differ diff --git a/docs/images/Dashboard_Resize_Menu.png b/docs/images/Dashboard_Resize_Menu.png new file mode 100644 index 00000000000000..ea9bff824c58ae Binary files /dev/null and b/docs/images/Dashboard_Resize_Menu.png differ diff --git a/docs/images/Dashboard_add_visualization.png b/docs/images/Dashboard_add_visualization.png new file mode 100644 index 00000000000000..47ac4325634833 Binary files /dev/null and b/docs/images/Dashboard_add_visualization.png differ diff --git a/docs/images/Dashboard_example.png b/docs/images/Dashboard_example.png new file mode 100644 index 00000000000000..f23e93ef806c3f Binary files /dev/null and b/docs/images/Dashboard_example.png differ diff --git a/docs/images/Dashboard_visualization_data.png b/docs/images/Dashboard_visualization_data.png new file mode 100644 index 00000000000000..7d2d49ef2ea681 Binary files /dev/null and b/docs/images/Dashboard_visualization_data.png differ diff --git a/docs/images/controls/controls_in_dashboard.png b/docs/images/controls/controls_in_dashboard.png new file mode 100644 index 00000000000000..5ea6b3ad0ca88a Binary files /dev/null and b/docs/images/controls/controls_in_dashboard.png differ diff --git a/docs/images/controls/controls_options.png b/docs/images/controls/controls_options.png new file mode 100644 index 00000000000000..aab93d5cd4be02 Binary files /dev/null and b/docs/images/controls/controls_options.png differ diff --git a/docs/images/controls/dropdown_control_editor.png b/docs/images/controls/dropdown_control_editor.png new file mode 100644 index 00000000000000..36a360dcd275e6 Binary files /dev/null and b/docs/images/controls/dropdown_control_editor.png differ diff --git a/docs/images/controls/range_slider_editor.png b/docs/images/controls/range_slider_editor.png new file mode 100644 index 00000000000000..8d6c5a68d1d24a Binary files /dev/null and b/docs/images/controls/range_slider_editor.png differ diff --git a/docs/images/management-index-management.png b/docs/images/management-index-management.png new file mode 100644 index 00000000000000..1b1ff9226147c5 Binary files /dev/null and b/docs/images/management-index-management.png differ diff --git a/docs/images/management-license.png b/docs/images/management-license.png new file mode 100644 index 00000000000000..8a4c1db6a9f728 Binary files /dev/null and b/docs/images/management-license.png differ diff --git a/docs/images/tsvb-gauge.png b/docs/images/tsvb-gauge.png index 8bfba642db97a6..62911655dda256 100644 Binary files a/docs/images/tsvb-gauge.png and b/docs/images/tsvb-gauge.png differ diff --git a/docs/images/tsvb-markdown.png b/docs/images/tsvb-markdown.png index a08839e4c7b0ca..97099d949d4183 100644 Binary files a/docs/images/tsvb-markdown.png and b/docs/images/tsvb-markdown.png differ diff --git a/docs/images/tsvb-metric.png b/docs/images/tsvb-metric.png index 27d8ea53f9854d..43e6cc0b7f8b34 100644 Binary files a/docs/images/tsvb-metric.png and b/docs/images/tsvb-metric.png differ diff --git a/docs/images/tsvb-table.png b/docs/images/tsvb-table.png new file mode 100644 index 00000000000000..092d9859b5bcd4 Binary files /dev/null and b/docs/images/tsvb-table.png differ diff --git a/docs/images/tsvb-timeseries.png b/docs/images/tsvb-timeseries.png index 29101c8376aff3..dfb0156732703f 100644 Binary files a/docs/images/tsvb-timeseries.png and b/docs/images/tsvb-timeseries.png differ diff --git a/docs/images/tsvb-top-n.png b/docs/images/tsvb-top-n.png index 1a4077c6aaecd0..ac39f2336dcd16 100644 Binary files a/docs/images/tsvb-top-n.png and b/docs/images/tsvb-top-n.png differ diff --git a/docs/images/tutorial-dashboard.png b/docs/images/tutorial-dashboard.png index cf660dd92a912d..5d4056cf7b11a8 100644 Binary files a/docs/images/tutorial-dashboard.png and b/docs/images/tutorial-dashboard.png differ diff --git a/docs/images/tutorial-discover-2.png b/docs/images/tutorial-discover-2.png index a3901abbaf93c8..338d58e1da21ea 100644 Binary files a/docs/images/tutorial-discover-2.png and b/docs/images/tutorial-discover-2.png differ diff --git a/docs/images/tutorial-discover-3.png b/docs/images/tutorial-discover-3.png index 2c36c667f91119..7531accd9a7efe 100644 Binary files a/docs/images/tutorial-discover-3.png and b/docs/images/tutorial-discover-3.png differ diff --git a/docs/images/tutorial-discover.png b/docs/images/tutorial-discover.png deleted file mode 100644 index 3d5bf84993ee2f..00000000000000 Binary files a/docs/images/tutorial-discover.png and /dev/null differ diff --git a/docs/images/tutorial-pattern-1.png b/docs/images/tutorial-pattern-1.png new file mode 100644 index 00000000000000..651dcba33aaa5d Binary files /dev/null and b/docs/images/tutorial-pattern-1.png differ diff --git a/docs/images/tutorial-timepicker.png b/docs/images/tutorial-timepicker.png deleted file mode 100644 index f1ac7befa451dd..00000000000000 Binary files a/docs/images/tutorial-timepicker.png and /dev/null differ diff --git a/docs/images/tutorial-visualize-bar-1.5.png b/docs/images/tutorial-visualize-bar-1.5.png new file mode 100644 index 00000000000000..e6d5de20edb1b8 Binary files /dev/null and b/docs/images/tutorial-visualize-bar-1.5.png differ diff --git a/docs/images/tutorial-visualize-bar-1.png b/docs/images/tutorial-visualize-bar-1.png index aafbd168daef54..1aad4f16a4922a 100644 Binary files a/docs/images/tutorial-visualize-bar-1.png and b/docs/images/tutorial-visualize-bar-1.png differ diff --git a/docs/images/tutorial-visualize-bar-2.png b/docs/images/tutorial-visualize-bar-2.png index 3f58ba749fdec4..244d4960ebed53 100644 Binary files a/docs/images/tutorial-visualize-bar-2.png and b/docs/images/tutorial-visualize-bar-2.png differ diff --git a/docs/images/tutorial-visualize-bar-3.png b/docs/images/tutorial-visualize-bar-3.png deleted file mode 100644 index 20bdf8fadfd88e..00000000000000 Binary files a/docs/images/tutorial-visualize-bar-3.png and /dev/null differ diff --git a/docs/images/tutorial-visualize-landing.png b/docs/images/tutorial-visualize-landing.png deleted file mode 100644 index a8400aacaaba2d..00000000000000 Binary files a/docs/images/tutorial-visualize-landing.png and /dev/null differ diff --git a/docs/images/tutorial-visualize-map-1.png b/docs/images/tutorial-visualize-map-1.png index ea10d88279519e..d9d8933d343a24 100644 Binary files a/docs/images/tutorial-visualize-map-1.png and b/docs/images/tutorial-visualize-map-1.png differ diff --git a/docs/images/tutorial-visualize-map-2.png b/docs/images/tutorial-visualize-map-2.png index 08464b55ee6c2c..9337bcdecd0e7a 100644 Binary files a/docs/images/tutorial-visualize-map-2.png and b/docs/images/tutorial-visualize-map-2.png differ diff --git a/docs/images/tutorial-visualize-map-3.png b/docs/images/tutorial-visualize-map-3.png index c0c47c7eac3f95..be3a8a83c4de03 100644 Binary files a/docs/images/tutorial-visualize-map-3.png and b/docs/images/tutorial-visualize-map-3.png differ diff --git a/docs/images/tutorial-visualize-md-1.png b/docs/images/tutorial-visualize-md-1.png deleted file mode 100644 index 55504682a0e5b0..00000000000000 Binary files a/docs/images/tutorial-visualize-md-1.png and /dev/null differ diff --git a/docs/images/tutorial-visualize-md-2.png b/docs/images/tutorial-visualize-md-2.png index c1bbc120aa0114..ec6d6f0278da82 100644 Binary files a/docs/images/tutorial-visualize-md-2.png and b/docs/images/tutorial-visualize-md-2.png differ diff --git a/docs/images/tutorial-visualize-pie-1.png b/docs/images/tutorial-visualize-pie-1.png index 613a4c080af9a0..229b061d006399 100644 Binary files a/docs/images/tutorial-visualize-pie-1.png and b/docs/images/tutorial-visualize-pie-1.png differ diff --git a/docs/images/tutorial-visualize-pie-2.png b/docs/images/tutorial-visualize-pie-2.png index fc2871c42aeef5..b4d41d996db673 100644 Binary files a/docs/images/tutorial-visualize-pie-2.png and b/docs/images/tutorial-visualize-pie-2.png differ diff --git a/docs/images/tutorial-visualize-pie-3.png b/docs/images/tutorial-visualize-pie-3.png index 340cad28c53deb..4fb0c2c5ef459e 100644 Binary files a/docs/images/tutorial-visualize-pie-3.png and b/docs/images/tutorial-visualize-pie-3.png differ diff --git a/docs/images/tutorial-visualize-wizard-step-1.png b/docs/images/tutorial-visualize-wizard-step-1.png index 798709a42d9456..f9aa5635fb1975 100644 Binary files a/docs/images/tutorial-visualize-wizard-step-1.png and b/docs/images/tutorial-visualize-wizard-step-1.png differ diff --git a/docs/images/tutorial-visualize-wizard-step-2.png b/docs/images/tutorial-visualize-wizard-step-2.png index 143392f3e234a1..32a915e4223370 100644 Binary files a/docs/images/tutorial-visualize-wizard-step-2.png and b/docs/images/tutorial-visualize-wizard-step-2.png differ diff --git a/docs/index-shared1.asciidoc b/docs/index-shared1.asciidoc deleted file mode 100644 index 95b3f37ef08a6e..00000000000000 --- a/docs/index-shared1.asciidoc +++ /dev/null @@ -1,17 +0,0 @@ - -include::{asciidoc-dir}/../../shared/versions.asciidoc[] - -:docker-repo: docker.elastic.co/kibana/kibana -:docker-image: docker.elastic.co/kibana/kibana:{version} -:repo: https://github.com/elastic/kibana/ -:issue: {repo}issues/ -:pull: {repo}pull/ -:commit: {repo}commit/ -:blob: {repo}blob/{branch}/ -:security-ref: https://www.elastic.co/community/security/ - -include::{asciidoc-dir}/../../shared/attributes.asciidoc[] - -include::introduction.asciidoc[] - -include::setup.asciidoc[] diff --git a/docs/index-shared2.asciidoc b/docs/index-shared2.asciidoc deleted file mode 100644 index 5c324bdf8d49d8..00000000000000 --- a/docs/index-shared2.asciidoc +++ /dev/null @@ -1,2 +0,0 @@ - -include::migration.asciidoc[] diff --git a/docs/index-shared3.asciidoc b/docs/index-shared3.asciidoc deleted file mode 100644 index 1543177752d0ea..00000000000000 --- a/docs/index-shared3.asciidoc +++ /dev/null @@ -1,11 +0,0 @@ - - -include::getting-started.asciidoc[] - -include::discover.asciidoc[] - -include::visualize.asciidoc[] - -include::dashboard.asciidoc[] - -include::timelion.asciidoc[] diff --git a/docs/index-shared5.asciidoc b/docs/index-shared5.asciidoc deleted file mode 100644 index d448bb691c99c0..00000000000000 --- a/docs/index-shared5.asciidoc +++ /dev/null @@ -1,2 +0,0 @@ - -include::management.asciidoc[] diff --git a/docs/index-shared6.asciidoc b/docs/index-shared6.asciidoc deleted file mode 100644 index 9e1931a2148f7e..00000000000000 --- a/docs/index-shared6.asciidoc +++ /dev/null @@ -1,8 +0,0 @@ - -include::plugins.asciidoc[] - -include::development.asciidoc[] - -include::limitations.asciidoc[] - -include::release-notes.asciidoc[] diff --git a/docs/index.asciidoc b/docs/index.asciidoc index 2f39bfc2928301..38d99f798afce6 100644 --- a/docs/index.asciidoc +++ b/docs/index.asciidoc @@ -1,9 +1,79 @@ [[kibana-guide]] = Kibana User Guide -include::index-shared1.asciidoc[] -include::index-shared2.asciidoc[] -include::index-shared3.asciidoc[] -include::index-shared4.asciidoc[] -include::index-shared5.asciidoc[] -include::index-shared6.asciidoc[] +:include-xpack: true +:lang: en +:kib-repo-dir: {docdir} +:blog-ref: https://www.elastic.co/blog/ +:wikipedia: https://en.wikipedia.org/wiki + +include::{asciidoc-dir}/../../shared/versions.asciidoc[] + +:docker-repo: docker.elastic.co/kibana/kibana +:docker-image: docker.elastic.co/kibana/kibana:{version} +:repo: https://github.com/elastic/kibana/ +:issue: {repo}issues/ +:pull: {repo}pull/ +:commit: {repo}commit/ +:blob: {repo}blob/{branch}/ +:security-ref: https://www.elastic.co/community/security/ + +include::{asciidoc-dir}/../../shared/attributes.asciidoc[] + +include::introduction.asciidoc[] + +include::setup.asciidoc[] + +include::setup/setup-xkb.asciidoc[] + +include::monitoring/monitoring-xkib.asciidoc[] + +include::security/securing-kibana.asciidoc[] + +include::settings/settings-xkb.asciidoc[] + +include::migration.asciidoc[] + +include::getting-started.asciidoc[] + +include::discover.asciidoc[] + +include::visualize.asciidoc[] + +include::dashboard.asciidoc[] + +include::timelion.asciidoc[] + +include::ml/index.asciidoc[] + +include::apm/index.asciidoc[] + +include::graph/index.asciidoc[] + +include::dev-tools.asciidoc[] + +include::monitoring/index.asciidoc[] + +include::management.asciidoc[] + +include::security/index.asciidoc[] + +include::management/watcher-ui/index.asciidoc[] + +include::management/upgrade-assistant/index.asciidoc[] + +include::management/dashboard_only_mode/index.asciidoc[] + +include::reporting/index.asciidoc[] + +include::api.asciidoc[] + +include::plugins.asciidoc[] + +include::development.asciidoc[] + +include::limitations.asciidoc[] + +include::release-notes/highlights.asciidoc[] + +include::CHANGELOG.asciidoc[] \ No newline at end of file diff --git a/docs/index.x.asciidoc b/docs/index.x.asciidoc index cf7ee289737f44..35204eef5b67e0 100644 --- a/docs/index.x.asciidoc +++ b/docs/index.x.asciidoc @@ -1,9 +1 @@ -[[kibana-guide]] -= Kibana User Guide - -:include-xpack: true -:lang: en -:kib-repo-dir: {docdir} -:xkb-repo-dir: {docdir}/../x-pack/docs/{lang} - -include::{xkb-repo-dir}/index.asciidoc[] +include::index.asciidoc[] diff --git a/docs/management.asciidoc b/docs/management.asciidoc index dac5ed8b32cfb2..e37a4225169529 100644 --- a/docs/management.asciidoc +++ b/docs/management.asciidoc @@ -10,13 +10,17 @@ the various "objects" that you can save throughout Kibana such as searches, visualizations, and dashboards. This section is pluginable, so in addition to the out of the box capabitilies, -packs such as X-Pack can add additional management capabilities to Kibana. +packs such as {xpack} can add additional management capabilities to Kibana. -- +include::management/managing-licenses.asciidoc[] + include::management/index-patterns.asciidoc[] include::management/managing-fields.asciidoc[] +include::management/managing-indices.asciidoc[] + include::management/advanced-options.asciidoc[] include::management/managing-saved-objects.asciidoc[] diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 0dc17c57bbeb44..1d31d32d7f4245 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -8,7 +8,7 @@ for displayed decimal values. To set advanced options: . Go to *Settings > Advanced*. -. Click the *Edit* button for the option you want to modify. +. Scroll or use the search bar to find the option you want to modify. . Enter a new value for the option. . Click the *Save* button. diff --git a/x-pack/docs/en/dashboard_only_mode/advanced_configuration.asciidoc b/docs/management/dashboard_only_mode/advanced_configuration.asciidoc similarity index 64% rename from x-pack/docs/en/dashboard_only_mode/advanced_configuration.asciidoc rename to docs/management/dashboard_only_mode/advanced_configuration.asciidoc index 9069def5550812..70114b6a0afafd 100644 --- a/x-pack/docs/en/dashboard_only_mode/advanced_configuration.asciidoc +++ b/docs/management/dashboard_only_mode/advanced_configuration.asciidoc @@ -6,14 +6,14 @@ Kibana comes preconfigured with a reserved role called `kibana_dashboard_only_us for most use cases. However, if your setup requires a custom Kibana index, you can manually create Dashboard Mode roles. -To do so, go into Management > Advanced Settings and search for `xpackDashboardMode:roles`. Then assign whatever +To do so, go into *Management > Advanced Settings* and search for `xpackDashboardMode:roles`. Then assign whatever role names you wish to use to flag a user for Dashboard Only mode. -image:dashboard_only_mode/images/advanced_dashboard_mode_role_setup.png["Advanced dashboard mode role setup"] +image:management/dashboard_only_mode/images/advanced_dashboard_mode_role_setup.png["Advanced dashboard mode role setup"] It isn't necessary for Dashboard Only mode roles to have any additional permissions, but it's a convenient location to also place access rules to the custom Kibana index. If you wish to grant read only access to your custom Kibana index, it must have `view_index_metadata` permissions as well as `read` permissions. These role settings are available -under Management > Security > Roles. +under *Management > Security > Roles*. -image:dashboard_only_mode/images/custom_dashboard_mode_role.png["Custom dashboard mode role with read permissions on a custom kibana index"] +image:management/dashboard_only_mode/images/custom_dashboard_mode_role.png["Custom dashboard mode role with read permissions on a custom kibana index"] diff --git a/x-pack/docs/en/dashboard_only_mode/images/advanced_dashboard_mode_role_setup.png b/docs/management/dashboard_only_mode/images/advanced_dashboard_mode_role_setup.png similarity index 100% rename from x-pack/docs/en/dashboard_only_mode/images/advanced_dashboard_mode_role_setup.png rename to docs/management/dashboard_only_mode/images/advanced_dashboard_mode_role_setup.png diff --git a/x-pack/docs/en/dashboard_only_mode/images/custom_dashboard_mode_role.png b/docs/management/dashboard_only_mode/images/custom_dashboard_mode_role.png similarity index 100% rename from x-pack/docs/en/dashboard_only_mode/images/custom_dashboard_mode_role.png rename to docs/management/dashboard_only_mode/images/custom_dashboard_mode_role.png diff --git a/x-pack/docs/en/dashboard_only_mode/images/view_only_dashboard.png b/docs/management/dashboard_only_mode/images/view_only_dashboard.png similarity index 100% rename from x-pack/docs/en/dashboard_only_mode/images/view_only_dashboard.png rename to docs/management/dashboard_only_mode/images/view_only_dashboard.png diff --git a/x-pack/docs/en/dashboard_only_mode/images/view_only_listing_page.png b/docs/management/dashboard_only_mode/images/view_only_listing_page.png similarity index 100% rename from x-pack/docs/en/dashboard_only_mode/images/view_only_listing_page.png rename to docs/management/dashboard_only_mode/images/view_only_listing_page.png diff --git a/x-pack/docs/en/dashboard_only_mode/index.asciidoc b/docs/management/dashboard_only_mode/index.asciidoc similarity index 83% rename from x-pack/docs/en/dashboard_only_mode/index.asciidoc rename to docs/management/dashboard_only_mode/index.asciidoc index c5f8b9a5f21a7a..67e1e896688aec 100644 --- a/x-pack/docs/en/dashboard_only_mode/index.asciidoc +++ b/docs/management/dashboard_only_mode/index.asciidoc @@ -8,9 +8,9 @@ reserved `kibana_dashboard_only_user` role. When you assign a user this role, the next time they sign in to Kibana they will only be able to see the Dashboard app, and no editing tools will be available. -image:dashboard_only_mode/images/view_only_listing_page.png["View Only Dashboard Listing Page"] +image:management/dashboard_only_mode/images/view_only_listing_page.png["View Only Dashboard Listing Page"] -image:dashboard_only_mode/images/view_only_dashboard.png["View Only Dashboard"] +image:management/dashboard_only_mode/images/view_only_dashboard.png["View Only Dashboard"] IMPORTANT: If a user is also assigned the reserved `superuser` role, they will be able to see all of Kibana and have full access. diff --git a/docs/management/index-patterns.asciidoc b/docs/management/index-patterns.asciidoc index 288d5ef8de270a..29182b85ec268f 100644 --- a/docs/management/index-patterns.asciidoc +++ b/docs/management/index-patterns.asciidoc @@ -73,6 +73,13 @@ To reload the index fields list: [float] [[delete-pattern]] == Deleting an Index Pattern +Deleting an index pattern removes the pattern from the list of Saved Objects in Kibana. +You will not be able to recover field formatters, scripted fields, source filters, and field popularity data +associated with the index pattern. + +Deleting an index pattern breaks all visualizations, saved searches, and other saved objects that reference the pattern. +Deleting a pattern does not remove any indices or data documents from Elasticsearch. + To delete an index pattern: . Go to the *Settings > Indices* tab. diff --git a/docs/management/managing-indices.asciidoc b/docs/management/managing-indices.asciidoc new file mode 100644 index 00000000000000..b5c0294fd64f18 --- /dev/null +++ b/docs/management/managing-indices.asciidoc @@ -0,0 +1,24 @@ +[[managing-indices]] +== Managing Indices + +The *Index management* UI enables you to view index settings, +mappings, and statistics and perform management operations. +These include refreshing, flushing, clearing the cache, merging segments, +and closing or deleting indices. The UI provides a convenient way to +perform bulk operations on multiple indices. + +[role="screenshot"] +image::images/management-index-management.png[Index Management UI] + +Click the name of an index to display the index summary and access +the index settings, mapping, and statistics. The *Manage* menu in the +lower right of the index pane enables you to manage +the selected index. + +To perform bulk operations, select the checkboxes of the indices you want to +modify and choose an operation from the *Manage indices* menu +next to the query bar. To select all +indices, select the checkbox in the *Name* header. + +For information about the available management operations, +see {ref}/indices.html[Indices APIs] in the Elasticsearch Reference. diff --git a/docs/management/managing-licenses.asciidoc b/docs/management/managing-licenses.asciidoc new file mode 100644 index 00000000000000..289e12da838aa1 --- /dev/null +++ b/docs/management/managing-licenses.asciidoc @@ -0,0 +1,23 @@ +[[managing-licenses]] +== License Management + +When you install Kibana, it generates a Basic license +with no expiration date. To start a 30-day trial, +view the status of your license, or install a new license +go to *Management* and click *License +Management*. + +[role="screenshot"] +image::images/management-license.png[] + +The 30-day trial enables you to try out the full set of +https://www.elastic.co/subscriptions[Platinum features], +including security, machine learning, alerting, graph capabilities, +and more. + +At the end of the trial period, your license reverts +to a Basic license. To continue using the Platinum features, +purchase a subscription and update your license. + +For a comparison of the Elastic license levels, +see https://www.elastic.co/subscriptions[the subscription page]. diff --git a/x-pack/docs/en/upgrade-assistant/index.asciidoc b/docs/management/upgrade-assistant/index.asciidoc similarity index 100% rename from x-pack/docs/en/upgrade-assistant/index.asciidoc rename to docs/management/upgrade-assistant/index.asciidoc diff --git a/x-pack/docs/en/management/watcher-ui/create-advanced-watch.asciidoc b/docs/management/watcher-ui/create-advanced-watch.asciidoc similarity index 71% rename from x-pack/docs/en/management/watcher-ui/create-advanced-watch.asciidoc rename to docs/management/watcher-ui/create-advanced-watch.asciidoc index 3f7f018cd6292d..3892ac18f04f87 100644 --- a/x-pack/docs/en/management/watcher-ui/create-advanced-watch.asciidoc +++ b/docs/management/watcher-ui/create-advanced-watch.asciidoc @@ -1,7 +1,8 @@ [[watcher-create-advanced-watch]] === Create Advanced Watch -Advanced watches are for people who are more familiar with Elasticsearch query syntax and the watcher framework overall. The creation UI is more closely aligned with using the REST apis directly. Please reference the https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html[Elasticsearch query DSL] for more information. +Advanced watches are for people who are more familiar with Elasticsearch query syntax and the watcher framework overall. The creation UI is more closely aligned with using the REST apis directly. For +more information, see {ref}/query-dsl.html[Query DSL]. To create a new advanced watch: @@ -16,7 +17,9 @@ This screen lets you define the core properties of an advanced watch. image:management/watcher-ui/images/advanced-watch/advanced-watch-create.png["Create Advanced Watch",link="management/watcher-ui/images/advanced-watch/advanced-watch-create.png"] -The `ID` refers to the identifier used by Elasticsearch, whereas `Name` is the more user-friendly way to identify the watch. Refer to the https://www.elastic.co/guide/en/x-pack/current/how-watcher-works.html#watch-definition[Watch definition documentation] for the Watch JSON. +The `ID` refers to the identifier used by Elasticsearch, whereas `Name` is the more user-friendly way to identify the watch. Refer to the +{stack-ov}/how-watcher-works.html#watch-definition[Watch definition documentation] +for the Watch JSON. [float] === Simulate @@ -27,10 +30,10 @@ This screen allows you to override parts of the watch and then run a simulation Some implementation details on overrides: -* Trigger overrides use https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#date-math[date math] +* Trigger overrides use {ref}/common-options.html#date-math[date math]. * Input override accepts a JSON blob that overrides the `input`. * Condition overrides is just a checkbox to indicate if you want to force the condition to always be true. -* Action overrides support multiple options, which are https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-execute-watch.html#watcher-api-execute-watch-action-mode[explained here] +* Action overrides support multiple options, which are {ref}/watcher-api-execute-watch.html#watcher-api-execute-watch-action-mode[explained here]. [float] === Simulated @@ -46,5 +49,6 @@ The possible simulation statuses for watches are: * `Ok` - The watch is not actively firing but working properly. * `Disabled` - The watch will not fire under any circumstance. -For more information on the various fields in the response, https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api-execute-watch.html[please refer to the Elasticsearch docs]. +For more information on the various fields in the response, see the +{ref}/watcher-api-execute-watch.html[Execute Watch API]. diff --git a/x-pack/docs/en/management/watcher-ui/create-threshold-alert.asciidoc b/docs/management/watcher-ui/create-threshold-alert.asciidoc similarity index 85% rename from x-pack/docs/en/management/watcher-ui/create-threshold-alert.asciidoc rename to docs/management/watcher-ui/create-threshold-alert.asciidoc index 8693fbf45aab78..7abe1ea73e3144 100644 --- a/x-pack/docs/en/management/watcher-ui/create-threshold-alert.asciidoc +++ b/docs/management/watcher-ui/create-threshold-alert.asciidoc @@ -61,15 +61,17 @@ Selecting an action will allow you to customize settings for the respective acti image:management/watcher-ui/images/threshold-alert/threshold-alert-action.png["Threshold Alert Logging Action",link="management/watcher-ui/images/threshold-alert/threshold-alert-action.png"] -All fields for an alert support using http://mustache.github.io/mustache.5.html[mustache syntax] and expose a `{{ctx}}` variable which exposes https://www.elastic.co/guide/en/watcher/current/condition.html#accessing-watch-payload[various properties of the alert] +All fields for an alert support using http://mustache.github.io/mustache.5.html[mustache syntax] and expose a `{{ctx}}` variable which exposes {stack-ov}/condition-script.html#accessing-watch-payload[various properties of the alert] The supported actions are: -* https://www.elastic.co/guide/en/watcher/current/actions.html#actions-slack[Slack] -* https://www.elastic.co/guide/en/watcher/current/actions.html#actions-logging[Logging] -* https://www.elastic.co/guide/en/watcher/current/actions.html#actions-email[Email] +* {stack-ov}/actions-slack.html[Slack] +* {stack-ov}/actions-logging.html[Logging] +* {stack-ov}/actions-email.html[Email] -Note that certain actions require configuration within ES, such as https://www.elastic.co/guide/en/x-pack/current/actions-email.html#configuring-email[email] and https://www.elastic.co/guide/en/x-pack/current/actions-slack.html#configuring-slack[slack]. +Note that certain actions require configuration within {es}, such as +{stack-ov}/actions-email.html#configuring-email[email] and +{stack-ov}/actions-slack.html#configuring-slack[slack]. include::create-advanced-watch.asciidoc[] diff --git a/x-pack/docs/en/management/watcher-ui/getting-started.asciidoc b/docs/management/watcher-ui/getting-started.asciidoc similarity index 100% rename from x-pack/docs/en/management/watcher-ui/getting-started.asciidoc rename to docs/management/watcher-ui/getting-started.asciidoc diff --git a/x-pack/docs/en/management/watcher-ui/images/advanced-watch/advanced-watch-create.png b/docs/management/watcher-ui/images/advanced-watch/advanced-watch-create.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/advanced-watch/advanced-watch-create.png rename to docs/management/watcher-ui/images/advanced-watch/advanced-watch-create.png diff --git a/x-pack/docs/en/management/watcher-ui/images/advanced-watch/advanced-watch-select.png b/docs/management/watcher-ui/images/advanced-watch/advanced-watch-select.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/advanced-watch/advanced-watch-select.png rename to docs/management/watcher-ui/images/advanced-watch/advanced-watch-select.png diff --git a/x-pack/docs/en/management/watcher-ui/images/advanced-watch/advanced-watch-simulate.png b/docs/management/watcher-ui/images/advanced-watch/advanced-watch-simulate.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/advanced-watch/advanced-watch-simulate.png rename to docs/management/watcher-ui/images/advanced-watch/advanced-watch-simulate.png diff --git a/x-pack/docs/en/management/watcher-ui/images/advanced-watch/advanced-watch-simulated.png b/docs/management/watcher-ui/images/advanced-watch/advanced-watch-simulated.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/advanced-watch/advanced-watch-simulated.png rename to docs/management/watcher-ui/images/advanced-watch/advanced-watch-simulated.png diff --git a/x-pack/docs/en/management/watcher-ui/images/create-watch-select.png b/docs/management/watcher-ui/images/create-watch-select.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/create-watch-select.png rename to docs/management/watcher-ui/images/create-watch-select.png diff --git a/x-pack/docs/en/management/watcher-ui/images/threshold-alert/create-threshold-alert-created.png b/docs/management/watcher-ui/images/threshold-alert/create-threshold-alert-created.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/threshold-alert/create-threshold-alert-created.png rename to docs/management/watcher-ui/images/threshold-alert/create-threshold-alert-created.png diff --git a/x-pack/docs/en/management/watcher-ui/images/threshold-alert/create-threshold-alert.png b/docs/management/watcher-ui/images/threshold-alert/create-threshold-alert.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/threshold-alert/create-threshold-alert.png rename to docs/management/watcher-ui/images/threshold-alert/create-threshold-alert.png diff --git a/x-pack/docs/en/management/watcher-ui/images/threshold-alert/high-heap-usage.png b/docs/management/watcher-ui/images/threshold-alert/high-heap-usage.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/threshold-alert/high-heap-usage.png rename to docs/management/watcher-ui/images/threshold-alert/high-heap-usage.png diff --git a/x-pack/docs/en/management/watcher-ui/images/threshold-alert/system-load.png b/docs/management/watcher-ui/images/threshold-alert/system-load.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/threshold-alert/system-load.png rename to docs/management/watcher-ui/images/threshold-alert/system-load.png diff --git a/x-pack/docs/en/management/watcher-ui/images/threshold-alert/threshold-alert-action.png b/docs/management/watcher-ui/images/threshold-alert/threshold-alert-action.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/threshold-alert/threshold-alert-action.png rename to docs/management/watcher-ui/images/threshold-alert/threshold-alert-action.png diff --git a/x-pack/docs/en/management/watcher-ui/images/threshold-alert/threshold-alert-aggType.png b/docs/management/watcher-ui/images/threshold-alert/threshold-alert-aggType.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/threshold-alert/threshold-alert-aggType.png rename to docs/management/watcher-ui/images/threshold-alert/threshold-alert-aggType.png diff --git a/x-pack/docs/en/management/watcher-ui/images/threshold-alert/threshold-alert-groupBy-pagination.png b/docs/management/watcher-ui/images/threshold-alert/threshold-alert-groupBy-pagination.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/threshold-alert/threshold-alert-groupBy-pagination.png rename to docs/management/watcher-ui/images/threshold-alert/threshold-alert-groupBy-pagination.png diff --git a/x-pack/docs/en/management/watcher-ui/images/threshold-alert/threshold-alert-select-action.png b/docs/management/watcher-ui/images/threshold-alert/threshold-alert-select-action.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/threshold-alert/threshold-alert-select-action.png rename to docs/management/watcher-ui/images/threshold-alert/threshold-alert-select-action.png diff --git a/x-pack/docs/en/management/watcher-ui/images/watches-custom.png b/docs/management/watcher-ui/images/watches-custom.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/watches-custom.png rename to docs/management/watcher-ui/images/watches-custom.png diff --git a/x-pack/docs/en/management/watcher-ui/images/watches.png b/docs/management/watcher-ui/images/watches.png similarity index 100% rename from x-pack/docs/en/management/watcher-ui/images/watches.png rename to docs/management/watcher-ui/images/watches.png diff --git a/x-pack/docs/en/management/watcher-ui/index.asciidoc b/docs/management/watcher-ui/index.asciidoc similarity index 66% rename from x-pack/docs/en/management/watcher-ui/index.asciidoc rename to docs/management/watcher-ui/index.asciidoc index ea59cfd2a2aee8..6a2b3a1aecad38 100644 --- a/x-pack/docs/en/management/watcher-ui/index.asciidoc +++ b/docs/management/watcher-ui/index.asciidoc @@ -2,7 +2,7 @@ [[watcher-ui]] == Watcher UI -_Watcher UI_ enables you to monitor, manage, create and simulate {xpack-ref}/xpack-alerting.html[watches] for your Elasticsearch -indices. +_Watcher UI_ enables you to monitor, manage, create and simulate +{stack-ov}/xpack-alerting.html[watches] for your Elasticsearch indices. include::getting-started.asciidoc[] diff --git a/x-pack/docs/en/management/watcher-ui/security.asciidoc b/docs/management/watcher-ui/security.asciidoc similarity index 72% rename from x-pack/docs/en/management/watcher-ui/security.asciidoc rename to docs/management/watcher-ui/security.asciidoc index 9c1fd386c7d3af..6eec927d0ca7a0 100644 --- a/x-pack/docs/en/management/watcher-ui/security.asciidoc +++ b/docs/management/watcher-ui/security.asciidoc @@ -7,4 +7,4 @@ The Watcher UI requires a user with `kibana_user` and the user must have either `watcher_user` can view all existing watches, but is not able to create or edit watches. -Learn more about creating users and roles in the https://www.elastic.co/guide/en/kibana/current/xpack-security.html[Security documentation]. +Learn more about creating users and roles in <>. diff --git a/docs/migration/migrate_7_0.asciidoc b/docs/migration/migrate_7_0.asciidoc index 06069c7f327bbb..ea021147459088 100644 --- a/docs/migration/migrate_7_0.asciidoc +++ b/docs/migration/migrate_7_0.asciidoc @@ -27,4 +27,17 @@ conflicted with the Advanced Setting. In 7.0 `query:queryString:options` will no users can have full control over their custom filters. *Impact:* You must ensure that any saved searches with a `query_string` filter aren't relying implicitly on -`query:queryString:options`. \ No newline at end of file +`query:queryString:options`. + +[float] +=== Advanced setting query:queryString:options no longer applies `default_field: *` by default. +*Details:* Elasticsearch removed the ability to create indices with an _all field in 6.0. As a result, a user could end +up with a mix of indices with and without _all fields if they upgraded from an older version of ES. This could lead to +inconsistent highlighting in Discover. To work around this issue we added `default_field: *` to query:queryString:options +to force consistent querying across indices with and without _all. In 7.0 the _all field will be gone from all indices +so we no longer need this workaround. + +*Impact:* Since we'll no longer send the `default_field` parameter in Kibana's query_string query, Elasticsearch +will use the index setting instead. The default for the index setting is also `*`, so most users should not be impacted. +If some of your indices have a non-default `default_field` setting, you may want to update it or re-add the parameter +to Kibana's advanced setting. \ No newline at end of file diff --git a/x-pack/docs/en/ml/creating-jobs.asciidoc b/docs/ml/creating-jobs.asciidoc similarity index 100% rename from x-pack/docs/en/ml/creating-jobs.asciidoc rename to docs/ml/creating-jobs.asciidoc diff --git a/x-pack/docs/en/ml/images/ml-calendar-management.jpg b/docs/ml/images/ml-calendar-management.jpg similarity index 100% rename from x-pack/docs/en/ml/images/ml-calendar-management.jpg rename to docs/ml/images/ml-calendar-management.jpg diff --git a/x-pack/docs/en/ml/images/ml-create-job.jpg b/docs/ml/images/ml-create-job.jpg similarity index 100% rename from x-pack/docs/en/ml/images/ml-create-job.jpg rename to docs/ml/images/ml-create-job.jpg diff --git a/x-pack/docs/en/ml/images/ml-data-recognizer.jpg b/docs/ml/images/ml-data-recognizer.jpg similarity index 100% rename from x-pack/docs/en/ml/images/ml-data-recognizer.jpg rename to docs/ml/images/ml-data-recognizer.jpg diff --git a/x-pack/docs/en/ml/images/ml-data-visualizer.jpg b/docs/ml/images/ml-data-visualizer.jpg similarity index 100% rename from x-pack/docs/en/ml/images/ml-data-visualizer.jpg rename to docs/ml/images/ml-data-visualizer.jpg diff --git a/x-pack/docs/en/ml/images/ml-job-management.jpg b/docs/ml/images/ml-job-management.jpg similarity index 100% rename from x-pack/docs/en/ml/images/ml-job-management.jpg rename to docs/ml/images/ml-job-management.jpg diff --git a/x-pack/docs/en/ml/images/ml-single-metric-viewer.jpg b/docs/ml/images/ml-single-metric-viewer.jpg similarity index 100% rename from x-pack/docs/en/ml/images/ml-single-metric-viewer.jpg rename to docs/ml/images/ml-single-metric-viewer.jpg diff --git a/x-pack/docs/en/ml/index.asciidoc b/docs/ml/index.asciidoc similarity index 100% rename from x-pack/docs/en/ml/index.asciidoc rename to docs/ml/index.asciidoc diff --git a/x-pack/docs/en/ml/job-tips.asciidoc b/docs/ml/job-tips.asciidoc similarity index 100% rename from x-pack/docs/en/ml/job-tips.asciidoc rename to docs/ml/job-tips.asciidoc diff --git a/x-pack/docs/en/monitoring/beats-details.asciidoc b/docs/monitoring/beats-details.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/beats-details.asciidoc rename to docs/monitoring/beats-details.asciidoc diff --git a/x-pack/docs/en/monitoring/cluster-alerts-license.asciidoc b/docs/monitoring/cluster-alerts-license.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/cluster-alerts-license.asciidoc rename to docs/monitoring/cluster-alerts-license.asciidoc diff --git a/x-pack/docs/en/monitoring/cluster-alerts.asciidoc b/docs/monitoring/cluster-alerts.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/cluster-alerts.asciidoc rename to docs/monitoring/cluster-alerts.asciidoc diff --git a/x-pack/docs/en/monitoring/configuring-monitoring.asciidoc b/docs/monitoring/configuring-monitoring.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/configuring-monitoring.asciidoc rename to docs/monitoring/configuring-monitoring.asciidoc diff --git a/x-pack/docs/en/monitoring/dashboards.asciidoc b/docs/monitoring/dashboards.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/dashboards.asciidoc rename to docs/monitoring/dashboards.asciidoc diff --git a/x-pack/docs/en/monitoring/elasticsearch-details.asciidoc b/docs/monitoring/elasticsearch-details.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/elasticsearch-details.asciidoc rename to docs/monitoring/elasticsearch-details.asciidoc diff --git a/x-pack/docs/en/monitoring/getting-started.asciidoc b/docs/monitoring/getting-started.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/getting-started.asciidoc rename to docs/monitoring/getting-started.asciidoc diff --git a/x-pack/docs/en/monitoring/gs-index.asciidoc b/docs/monitoring/gs-index.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/gs-index.asciidoc rename to docs/monitoring/gs-index.asciidoc diff --git a/x-pack/docs/en/monitoring/images/monitoring-architecture.png b/docs/monitoring/images/monitoring-architecture.png similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-architecture.png rename to docs/monitoring/images/monitoring-architecture.png diff --git a/x-pack/docs/en/monitoring/images/monitoring-beats-detail.jpg b/docs/monitoring/images/monitoring-beats-detail.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-beats-detail.jpg rename to docs/monitoring/images/monitoring-beats-detail.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-beats.jpg b/docs/monitoring/images/monitoring-beats.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-beats.jpg rename to docs/monitoring/images/monitoring-beats.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-es-cgroup-true.png b/docs/monitoring/images/monitoring-es-cgroup-true.png similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-es-cgroup-true.png rename to docs/monitoring/images/monitoring-es-cgroup-true.png diff --git a/x-pack/docs/en/monitoring/images/monitoring-index-advanced.jpg b/docs/monitoring/images/monitoring-index-advanced.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-index-advanced.jpg rename to docs/monitoring/images/monitoring-index-advanced.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-index-advanced.png b/docs/monitoring/images/monitoring-index-advanced.png similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-index-advanced.png rename to docs/monitoring/images/monitoring-index-advanced.png diff --git a/x-pack/docs/en/monitoring/images/monitoring-index.jpg b/docs/monitoring/images/monitoring-index.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-index.jpg rename to docs/monitoring/images/monitoring-index.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-indices.jpg b/docs/monitoring/images/monitoring-indices.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-indices.jpg rename to docs/monitoring/images/monitoring-indices.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-kibana-instance.jpg b/docs/monitoring/images/monitoring-kibana-instance.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-kibana-instance.jpg rename to docs/monitoring/images/monitoring-kibana-instance.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-kibana-instances.jpg b/docs/monitoring/images/monitoring-kibana-instances.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-kibana-instances.jpg rename to docs/monitoring/images/monitoring-kibana-instances.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-kibana-overview.jpg b/docs/monitoring/images/monitoring-kibana-overview.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-kibana-overview.jpg rename to docs/monitoring/images/monitoring-kibana-overview.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-logstash-node.jpg b/docs/monitoring/images/monitoring-logstash-node.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-logstash-node.jpg rename to docs/monitoring/images/monitoring-logstash-node.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-logstash-nodes.jpg b/docs/monitoring/images/monitoring-logstash-nodes.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-logstash-nodes.jpg rename to docs/monitoring/images/monitoring-logstash-nodes.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-logstash-overview.jpg b/docs/monitoring/images/monitoring-logstash-overview.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-logstash-overview.jpg rename to docs/monitoring/images/monitoring-logstash-overview.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-multicluster.jpg b/docs/monitoring/images/monitoring-multicluster.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-multicluster.jpg rename to docs/monitoring/images/monitoring-multicluster.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-node-advanced.jpg b/docs/monitoring/images/monitoring-node-advanced.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-node-advanced.jpg rename to docs/monitoring/images/monitoring-node-advanced.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-node-advanced.png b/docs/monitoring/images/monitoring-node-advanced.png similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-node-advanced.png rename to docs/monitoring/images/monitoring-node-advanced.png diff --git a/x-pack/docs/en/monitoring/images/monitoring-node.jpg b/docs/monitoring/images/monitoring-node.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-node.jpg rename to docs/monitoring/images/monitoring-node.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-nodes.jpg b/docs/monitoring/images/monitoring-nodes.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-nodes.jpg rename to docs/monitoring/images/monitoring-nodes.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-overview-shards.jpg b/docs/monitoring/images/monitoring-overview-shards.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-overview-shards.jpg rename to docs/monitoring/images/monitoring-overview-shards.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring-overview.jpg b/docs/monitoring/images/monitoring-overview.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring-overview.jpg rename to docs/monitoring/images/monitoring-overview.jpg diff --git a/x-pack/docs/en/monitoring/images/monitoring.jpg b/docs/monitoring/images/monitoring.jpg similarity index 100% rename from x-pack/docs/en/monitoring/images/monitoring.jpg rename to docs/monitoring/images/monitoring.jpg diff --git a/x-pack/docs/en/monitoring/images/sense.png b/docs/monitoring/images/sense.png similarity index 100% rename from x-pack/docs/en/monitoring/images/sense.png rename to docs/monitoring/images/sense.png diff --git a/x-pack/docs/en/monitoring/images/sense_thumb.png b/docs/monitoring/images/sense_thumb.png similarity index 100% rename from x-pack/docs/en/monitoring/images/sense_thumb.png rename to docs/monitoring/images/sense_thumb.png diff --git a/x-pack/docs/en/monitoring/index.asciidoc b/docs/monitoring/index.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/index.asciidoc rename to docs/monitoring/index.asciidoc diff --git a/x-pack/docs/en/monitoring/kibana-details.asciidoc b/docs/monitoring/kibana-details.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/kibana-details.asciidoc rename to docs/monitoring/kibana-details.asciidoc diff --git a/x-pack/docs/en/monitoring/logstash-details.asciidoc b/docs/monitoring/logstash-details.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/logstash-details.asciidoc rename to docs/monitoring/logstash-details.asciidoc diff --git a/x-pack/docs/en/monitoring/monitoring-details.asciidoc b/docs/monitoring/monitoring-details.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/monitoring-details.asciidoc rename to docs/monitoring/monitoring-details.asciidoc diff --git a/x-pack/docs/en/monitoring/monitoring-elasticsearch.asciidoc b/docs/monitoring/monitoring-elasticsearch.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/monitoring-elasticsearch.asciidoc rename to docs/monitoring/monitoring-elasticsearch.asciidoc diff --git a/x-pack/docs/en/monitoring/monitoring-kibana.asciidoc b/docs/monitoring/monitoring-kibana.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/monitoring-kibana.asciidoc rename to docs/monitoring/monitoring-kibana.asciidoc diff --git a/x-pack/docs/en/monitoring/monitoring-logstash.asciidoc b/docs/monitoring/monitoring-logstash.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/monitoring-logstash.asciidoc rename to docs/monitoring/monitoring-logstash.asciidoc diff --git a/x-pack/docs/en/monitoring/monitoring-troubleshooting.asciidoc b/docs/monitoring/monitoring-troubleshooting.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/monitoring-troubleshooting.asciidoc rename to docs/monitoring/monitoring-troubleshooting.asciidoc diff --git a/x-pack/docs/en/monitoring/monitoring-xkib.asciidoc b/docs/monitoring/monitoring-xkib.asciidoc similarity index 95% rename from x-pack/docs/en/monitoring/monitoring-xkib.asciidoc rename to docs/monitoring/monitoring-xkib.asciidoc index d1f8af86216c1b..02602659cee9d0 100644 --- a/x-pack/docs/en/monitoring/monitoring-xkib.asciidoc +++ b/docs/monitoring/monitoring-xkib.asciidoc @@ -5,6 +5,10 @@ Configuring Monitoring ++++ +{monitoring} gives you insight into the operation of your {stack}. For more +information, see <> and +{stack-ov}/xpack-monitoring.html[Monitoring the {stack}]. + . To monitor {kib}: .. Verify that the `xpack.monitoring.collection.enabled` setting is `true` on @@ -127,4 +131,4 @@ and the monitoring cluster. See also <>. -include::{xkb-repo-dir}/settings/monitoring-settings.asciidoc[] +include::{kib-repo-dir}/settings/monitoring-settings.asciidoc[] diff --git a/x-pack/docs/en/monitoring/viewing-metrics.asciidoc b/docs/monitoring/viewing-metrics.asciidoc similarity index 100% rename from x-pack/docs/en/monitoring/viewing-metrics.asciidoc rename to docs/monitoring/viewing-metrics.asciidoc diff --git a/docs/plugins.asciidoc b/docs/plugins.asciidoc index 454b6c2e329580..cc58b17771d5d1 100644 --- a/docs/plugins.asciidoc +++ b/docs/plugins.asciidoc @@ -15,7 +15,7 @@ The Kibana plugin interfaces are in a state of constant development. We cannot ============================================== -- -[[_installing_plugins]] +[[install-plugin]] == Installing Plugins Use the following command to install a plugin: @@ -52,7 +52,7 @@ $ bin/kibana-plugin install file:///some/local/path/my-plugin.zip -d path/to/dir NOTE: This command creates the specified directory if it does not already exist. -WARNING: This option is deprecated and will be removed in Kibana 7. It is known to not work with some plugins, including X-Pack. +WARNING: This option is deprecated and will be removed in Kibana 7. It is known to not work with some plugins, including {xpack}. [float] === Installing Plugins with Linux packages @@ -82,6 +82,7 @@ You can specify the environment variable directly when installing plugins: $ http_proxy="http://proxy.local:4242" bin/kibana-plugin install +[[update-remove-plugin]] == Updating & Removing Plugins To update a plugin, remove the current version and reinstall the plugin. @@ -95,6 +96,7 @@ You can also remove a plugin manually by deleting the plugin's subdirectory unde NOTE: Removing a plugin will result in an "optimize" run which will delay the next start of Kibana. +[[disable-plugin]] == Disabling Plugins Use the following command to disable a plugin: @@ -108,6 +110,7 @@ NOTE: Disabling or enabling a plugin will result in an "optimize" run which will <1> You can find a plugin's plugin ID as the value of the `name` property in the plugin's `package.json` file. +[[configure-plugin-manager]] == Configuring the Plugin Manager By default, the plugin manager provides you with feedback on the status of the activity you've asked the plugin manager diff --git a/docs/plugins/known-plugins.asciidoc b/docs/plugins/known-plugins.asciidoc index f1017b802c2020..b1ff3b53412e71 100644 --- a/docs/plugins/known-plugins.asciidoc +++ b/docs/plugins/known-plugins.asciidoc @@ -9,10 +9,6 @@ The Kibana plugin interfaces are in a state of constant development. We cannot This list of plugins is not guaranteed to work on your version of Kibana. Instead, these are plugins that were known to work at some point with Kibana *5.x*. The Kibana installer will reject any plugins that haven't been published for your specific version of Kibana. -[float] -=== Packs -* https://www.elastic.co/downloads/x-pack[X-Pack] - security, monitoring, reporting, alerts, graph - [float] === Apps * https://github.com/sivasamyk/logtrail[LogTrail] - View, analyze, search and tail log events in realtime with a developer/sysadmin friendly interface @@ -30,6 +26,7 @@ This list of plugins is not guaranteed to work on your version of Kibana. Instea === Visualizations * https://github.com/virusu/3D_kibana_charts_vis[3D Charts] (virusu) * https://github.com/JuanCarniglia/area3d_vis[3D Graph] (JuanCarniglia) +* https://github.com/TrumanDu/bmap[Bmap](TrumanDu) - integrated echarts for map visualization * https://github.com/mstoyano/kbn_c3js_vis[C3JS Visualizations] (mstoyano) * https://github.com/elo7/cohort[Cohort analysis] (elo7) * https://github.com/DeanF/health_metric_vis[Colored Metric Visualization] (deanf) @@ -43,6 +40,7 @@ This list of plugins is not guaranteed to work on your version of Kibana. Instea * https://github.com/clamarque/Kibana_health_metric_vis[Health Metric] (clamarque) * https://github.com/sbeyn/kibana-plugin-line-sg[Line] (sbeyn) * https://github.com/walterra/kibana-milestones-vis[Milestones] (walterra) +* https://github.com/varundbest/navigation[Navigation] (varundbest) * https://github.com/dlumbrer/kbn_network[Network Plugin] (dlumbrer) * https://github.com/amannocci/kibana-plugin-metric-percent[Percent] (amannocci) * https://github.com/dlumbrer/kbn_polar[Polar] (dlumbrer) diff --git a/docs/release-notes/6.0.0-alpha1.asciidoc b/docs/release-notes/6.0.0-alpha1.asciidoc deleted file mode 100644 index dd047c4114a743..00000000000000 --- a/docs/release-notes/6.0.0-alpha1.asciidoc +++ /dev/null @@ -1,78 +0,0 @@ -[[release-notes-6.0.0-alpha1]] -== 6.0.0-alpha1 Release Notes - -Also see <>. - -[float] -[[enhancement-6.0.0-alpha1]] -=== Enhancements -Core:: -* Deprecate Bootstrap buttons {pull}11352[#11352] -* Fix missing border of PaginatedTable rows in Firefox {pull}11452[#11452] -* Reinstate a few Bootstrap btn classes to support angular-ui-select. {pull}11569[#11569] -* Remove Bootstrap btn classes. {pull}11353[#11353] -* [UI Framework] Add AssistedInput. {pull}11343[#11343] -* [UI Framework] Add example of disabled kuiSelect. {pull}11345[#11345] -* [UI Framework] Add example of spinner Icon. {pull}11424[#11424] -* [UI Framework] Add kuiButton--fullWidth kuiButton--small, and kuiButtonGroup--fullWidth modifiers. {pull}11365[#11365] -* [UI Framework] Add support for dark theme links. {pull}11344[#11344] -* [UI Framework] Add support for selects and secondary inputs to LocalNavSearch component of UI Framework. {pull}11287[#11287] -* [UI Framework] Apply elastic.co look and feel to UI Framework docs site. {pull}11174[#11174] -* [UI Framework] Fix appearance of some form components in Firefox {pull}11589[#11589] -* [UI Framework] Make CardGroup split apart by default. Add kuiCardGroup--united modifier. {pull}11580[#11580] -* [UI Framework] Vertical align children in a FieldGroup. {pull}11374[#11374] -* Add small text input to UI framework {pull}11354[#11354] -* [UI Framework] Add uiFramework:build task. {pull}11402[#11402] -* Updates to status API, re-align status page {pull}10180[#10180] -* [status] 15m load average should use the 3rd index {pull}11202[#11202] -* Sets ES mapping to single_type=false {pull}11451[#11451] -Dev Tools:: -* Adding autocomplete rules for reindex API to Console {pull}10150[#10150] -* minimum_number_should_match was deprecated {pull}11316[#11316] -Dashboard:: -* Improve Dashboard screen-reader accessibility. {pull}11600[#11600] -* Update angular-bootstrap DatePicker with UI Framework classes. {pull}11378[#11378] -* Finish loading a dashboard even if some visualizations throw errors {pull}11324[#11324] -* React search box tool bar {pull}10821[#10821] -* Don't kill an entire dashboard because of one bad request {pull}11337[#11337] -* Add back dashboard descriptions {pull}11552[#11552] -* Hide the second toast when adding a new visualization straight from dashboard {pull}11621[#11621] -Discover:: -* Add ignore_unmapped to geo filters to prevent exceptions {pull}11461[#11461] -* Create CollapseButton component class to standardize appearance of this button. {pull}11462[#11462] -* Migrate deprecated match query syntax {pull}11554[#11554] -* Remove the _source field toggle button which was accidentally reinstated {pull}11485[#11485] -* Search bar drop-down for managing filters {pull}10976[#10976] -Management:: -* Convert Index Pattern Creation form UI to use UI Framework components. {pull}11419[#11419] -* Convert ScriptedFieldsTable and SourceFiltersTable to UI Framework components. {pull}11401[#11401] -* Removes the "Index contains time-based events" checkbox {pull}11409[#11409] -* Update Settings page with UI Framework components. {pull}11272[#11272] -* Report shard failures in the field_capabilities response {pull}11450[#11450] -Visualize:: -* Fix spelling in time series visual builder {pull}11212[#11212] -* Adding label templates to legend keys for TSVB {pull}11266[#11266] -* Fix missing icons in Visualize listing. {pull}11243[#11243] -* Update illegible vis type icons with legible ones. {pull}11317[#11317] -* Fixing the fields for the numbers for percentile aggs for Time Series Visual Builder {pull}11169[#11169] -* using ui-select for field selection in visualize {pull}10998[#10998] -* add polygon drawing tool {pull}11578[#11578] -* Fix timelion's flot when neither thor nor monitoring are installed {pull}10412[#10412] - -[float] -[[bug-6.0.0-alpha1]] -=== Bug fixes -Core:: -* [Fix for #4964] Disable dynamic/Implement static mappings {pull}10638[#10638] -* Fix visualize sort icon bug {pull}11568[#11568] -Visualize:: -* Fixes #11232 - Add option for panel and global filters to annotations for TSVB {pull}11260[#11260] -* Fixes #11289 - Change top_n to not use split colors for TSVB {pull}11342[#11342] -* [Fix for #10907] allows more flexible timelion queries {pull}10961[#10961] -* [Fix for #10292] fixing heatmap black squares {pull}11489[#11489] -* [Fix for #4599] Add "Sum of series in legend" option {pull}7970[#7970] -* [Fix for #9053] [timelion/fit/carry] do nothing if there is not any data {pull}9054[#9054] -* [Fix for #8763] [vislib/tilemap/heatmap] scale the heatmap maxZoom with map zoom {pull}8765[#8765] -* [Fix for #9184] fixes error with custom interval in datetime aggregation {pull}9427[#9427] - - diff --git a/docs/release-notes/6.0.0-alpha2.asciidoc b/docs/release-notes/6.0.0-alpha2.asciidoc deleted file mode 100644 index 080bb7715c140e..00000000000000 --- a/docs/release-notes/6.0.0-alpha2.asciidoc +++ /dev/null @@ -1,52 +0,0 @@ -[[release-notes-6.0.0-alpha2]] -== 6.0.0-alpha2 Release Notes - -Also see <>. - - -[float] -[[breaking-6.0.0-alpha2]] -=== Breaking changes -Core:: -* Remove legacy pre-4.2 configurations {pull}12013[#12013] -* NODE_ENV no longer has an impact on Kibana {pull}12010[#12010] -* Only support 64 bit operating systems {pull}11941[#11941] - - -[float] -[[feature-6.0.0-alpha2]] -=== New features -Core:: -* Getting started page {pull}11805[#11805] -Dashboard:: -* Clone dashboard from view mode {pull}10925[#10925] -Visualize:: -* Region map {pull}10937[#10937] -* Gauge chart {pull}10336[#10336] - - -[float] -[[enhancement-6.0.0-alpha2]] -=== Enhancements -Core:: -* Add new UI setting to control the amount of items in listing pages {pull}11674[#11674] -Discover:: -* Apply filters to the event context view {pull}11466[#11466] -Timelion:: -* Support multiline Timelion queries {pull}11972[#11972] -Time series visual builder:: -* Help text for writing painless scripts {pull}11936[#11936] -* Toggle for automatically applying changes to visualization {pull}11460[#11460] -Timepicker:: -* Improve accessibility of the datepicker {pull}11753[#11753] - - -[float] -[[bug-6.0.0-alpha2]] -=== Bug fixes -Timelion:: -* Timelion tutorial now persists until you close it {pull}11962[#11962] -Time series visual builder:: -* No longer trigger error in certain circumstances when using using percentiles {pull}11772[#11772] -Visualize:: -* Disable save button if visualization is dirty {pull}11576[#11576] diff --git a/docs/release-notes/7.0.0-alpha1.asciidoc b/docs/release-notes/7.0.0-alpha1.asciidoc deleted file mode 100644 index 0df1c0a4e3a3df..00000000000000 --- a/docs/release-notes/7.0.0-alpha1.asciidoc +++ /dev/null @@ -1,11 +0,0 @@ -[[release-notes-7.0.0-alpha1]] -== 7.0.0-alpha1 Release Notes - -The changes listed below have been released for the first time in {kib} -7.0.0-alpha1. - -[float] -[[enhancement-7.0.0-alpha1]] -=== Breaking Changes - -No breaking changes have been made yet. diff --git a/docs/release-notes/highlights-7.0.0.asciidoc b/docs/release-notes/highlights-7.0.0.asciidoc new file mode 100644 index 00000000000000..6023f6d87355cb --- /dev/null +++ b/docs/release-notes/highlights-7.0.0.asciidoc @@ -0,0 +1,9 @@ +[[release-highlights-7.0.0]] +== 7.0.0 release highlights +++++ +7.0.0 +++++ + +coming[7.0.0] + +See also <> and <>. \ No newline at end of file diff --git a/docs/release-notes/highlights.asciidoc b/docs/release-notes/highlights.asciidoc new file mode 100644 index 00000000000000..c9db7d83b62c27 --- /dev/null +++ b/docs/release-notes/highlights.asciidoc @@ -0,0 +1,16 @@ +[[release-highlights]] += {kib} Release Highlights +++++ +Release Highlights +++++ + +[partintro] +-- +This section summarizes the most important changes in each release. For the +full list, see <> and <>. + +* <> + +-- + +include::highlights-7.0.0.asciidoc[] \ No newline at end of file diff --git a/x-pack/docs/en/reporting/automating-report-generation.asciidoc b/docs/reporting/automating-report-generation.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/automating-report-generation.asciidoc rename to docs/reporting/automating-report-generation.asciidoc diff --git a/x-pack/docs/en/reporting/chromium-sandbox.asciidoc b/docs/reporting/chromium-sandbox.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/chromium-sandbox.asciidoc rename to docs/reporting/chromium-sandbox.asciidoc diff --git a/x-pack/docs/en/reporting/configuring-reporting.asciidoc b/docs/reporting/configuring-reporting.asciidoc similarity index 96% rename from x-pack/docs/en/reporting/configuring-reporting.asciidoc rename to docs/reporting/configuring-reporting.asciidoc index f1497494204c83..d6a69a1019aa36 100644 --- a/x-pack/docs/en/reporting/configuring-reporting.asciidoc +++ b/docs/reporting/configuring-reporting.asciidoc @@ -28,4 +28,4 @@ communicates with the Kibana server, manages background jobs, and captures screenshots. See <> for the complete list of settings. -include::{xkb-repo-dir}/security/reporting.asciidoc[] +include::{kib-repo-dir}/security/reporting.asciidoc[] diff --git a/x-pack/docs/en/reporting/development/csv-integration.asciidoc b/docs/reporting/development/csv-integration.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/development/csv-integration.asciidoc rename to docs/reporting/development/csv-integration.asciidoc diff --git a/x-pack/docs/en/reporting/development/index.asciidoc b/docs/reporting/development/index.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/development/index.asciidoc rename to docs/reporting/development/index.asciidoc diff --git a/x-pack/docs/en/reporting/development/pdf-integration.asciidoc b/docs/reporting/development/pdf-integration.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/development/pdf-integration.asciidoc rename to docs/reporting/development/pdf-integration.asciidoc diff --git a/x-pack/docs/en/reporting/getting-started.asciidoc b/docs/reporting/getting-started.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/getting-started.asciidoc rename to docs/reporting/getting-started.asciidoc diff --git a/x-pack/docs/en/reporting/gs-index.asciidoc b/docs/reporting/gs-index.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/gs-index.asciidoc rename to docs/reporting/gs-index.asciidoc diff --git a/x-pack/docs/en/reporting/images/csv-reporting.png b/docs/reporting/images/csv-reporting.png similarity index 100% rename from x-pack/docs/en/reporting/images/csv-reporting.png rename to docs/reporting/images/csv-reporting.png diff --git a/x-pack/docs/en/reporting/images/pdf-reporting.png b/docs/reporting/images/pdf-reporting.png similarity index 100% rename from x-pack/docs/en/reporting/images/pdf-reporting.png rename to docs/reporting/images/pdf-reporting.png diff --git a/x-pack/docs/en/reporting/images/preserve-layout.png b/docs/reporting/images/preserve-layout.png similarity index 100% rename from x-pack/docs/en/reporting/images/preserve-layout.png rename to docs/reporting/images/preserve-layout.png diff --git a/x-pack/docs/en/reporting/images/print-layout.png b/docs/reporting/images/print-layout.png similarity index 100% rename from x-pack/docs/en/reporting/images/print-layout.png rename to docs/reporting/images/print-layout.png diff --git a/x-pack/docs/en/reporting/images/reporting-button.png b/docs/reporting/images/reporting-button.png similarity index 100% rename from x-pack/docs/en/reporting/images/reporting-button.png rename to docs/reporting/images/reporting-button.png diff --git a/x-pack/docs/en/reporting/index.asciidoc b/docs/reporting/index.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/index.asciidoc rename to docs/reporting/index.asciidoc diff --git a/x-pack/docs/en/reporting/pdf-layout-modes.asciidoc b/docs/reporting/pdf-layout-modes.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/pdf-layout-modes.asciidoc rename to docs/reporting/pdf-layout-modes.asciidoc diff --git a/x-pack/docs/en/reporting/report-intervals.asciidoc b/docs/reporting/report-intervals.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/report-intervals.asciidoc rename to docs/reporting/report-intervals.asciidoc diff --git a/x-pack/docs/en/reporting/reporting-troubleshooting.asciidoc b/docs/reporting/reporting-troubleshooting.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/reporting-troubleshooting.asciidoc rename to docs/reporting/reporting-troubleshooting.asciidoc diff --git a/x-pack/docs/en/reporting/watch-example.asciidoc b/docs/reporting/watch-example.asciidoc similarity index 100% rename from x-pack/docs/en/reporting/watch-example.asciidoc rename to docs/reporting/watch-example.asciidoc diff --git a/x-pack/docs/en/security/authentication/index.asciidoc b/docs/security/authentication/index.asciidoc similarity index 99% rename from x-pack/docs/en/security/authentication/index.asciidoc rename to docs/security/authentication/index.asciidoc index f0b78779dd24b3..9839975eaee14b 100644 --- a/x-pack/docs/en/security/authentication/index.asciidoc +++ b/docs/security/authentication/index.asciidoc @@ -1,6 +1,9 @@ [role="xpack"] [[kibana-authentication]] === Authentication in Kibana +++++ +Authentication +++++ {kib} supports the following authentication mechanisms: diff --git a/x-pack/docs/en/security/cross-cluster-kibana.asciidoc b/docs/security/cross-cluster-kibana.asciidoc similarity index 100% rename from x-pack/docs/en/security/cross-cluster-kibana.asciidoc rename to docs/security/cross-cluster-kibana.asciidoc diff --git a/x-pack/docs/en/security/images/kibana-login.jpg b/docs/security/images/kibana-login.jpg similarity index 100% rename from x-pack/docs/en/security/images/kibana-login.jpg rename to docs/security/images/kibana-login.jpg diff --git a/x-pack/docs/en/security/index.asciidoc b/docs/security/index.asciidoc similarity index 100% rename from x-pack/docs/en/security/index.asciidoc rename to docs/security/index.asciidoc diff --git a/x-pack/docs/en/security/reporting.asciidoc b/docs/security/reporting.asciidoc similarity index 100% rename from x-pack/docs/en/security/reporting.asciidoc rename to docs/security/reporting.asciidoc diff --git a/docs/security/securing-communications/index.asciidoc b/docs/security/securing-communications/index.asciidoc new file mode 100644 index 00000000000000..e6b3987b360140 --- /dev/null +++ b/docs/security/securing-communications/index.asciidoc @@ -0,0 +1,91 @@ +[[configuring-tls]] +=== Encrypting communications in {kib} +++++ +Encrypting communications +++++ + +{kib} supports Transport Layer Security (TLS/SSL) encryption for client +requests. +//TBD: It is unclear what "client requests" are in this context. Is it just +// communication between the browser and the Kibana server or are we talking +// about other types of clients connecting to the Kibana server? + +If you are using {security} or a proxy that provides an HTTPS endpoint for {es}, +you can configure {kib} to access {es} via HTTPS. Thus, communications between +{kib} and {es} are also encrypted. + +. Configure {kib} to encrypt communications between the browser and the {kib} +server: ++ +-- +NOTE: You do not need to enable {security} for this type of encryption. + +-- + +.. Generate a server certificate for {kib}. ++ +-- +//TBD: Can we provide more information about how they generate the certificate? +//Would they be able to use something like the elasticsearch-certutil command? +You must either set the certificate's +`subjectAltName` to the hostname, fully-qualified domain name (FQDN), or IP +address of the {kib} server, or set the CN to the {kib} server's hostname +or FQDN. Using the server's IP address as the CN does not work. +-- + +.. Set the `server.ssl.enabled`, `server.ssl.key`, and `server.ssl.certificate` +properties in `kibana.yml`: ++ +-- +[source,yaml] +-------------------------------------------------------------------------------- +server.ssl.enabled: true +server.ssl.key: /path/to/your/server.key +server.ssl.certificate: /path/to/your/server.crt +-------------------------------------------------------------------------------- + +After making these changes, you must always access {kib} via HTTPS. For example, +https://localhost:5601. + +// TBD: The reference information for server.ssl.enabled says it "enables SSL for +// outgoing requests from the Kibana server to the browser". Do we need to +// reiterate here that only one side of the communications is encrypted? + +For more information, see <>. +-- + +. Configure {kib} to connect to {es} via HTTPS: ++ +-- +NOTE: To perform this step, you must +{ref}/configuring-security.html[enable the {security} feature in {es}] or you +must have a proxy that provides an HTTPS endpoint for {es}. + +-- + +.. Specify the HTTPS protocol in the `elasticsearch.url` setting in the {kib} +configuration file, `kibana.yml`: ++ +-- +[source,yaml] +-------------------------------------------------------------------------------- +elasticsearch.url: "https://.com:9200" +-------------------------------------------------------------------------------- +-- + +.. If you are using your own CA to sign certificates for {es}, set the +`elasticsearch.ssl.certificateAuthorities` setting in `kibana.yml` to specify +the location of the PEM file. ++ +-- +[source,yaml] +-------------------------------------------------------------------------------- +elasticsearch.ssl.certificateAuthorities: /path/to/your/cacert.pem +-------------------------------------------------------------------------------- + +Setting the `certificateAuthorities` property lets you use the default +`verificationMode` option of `full`. +//TBD: Is this still true? It isn't mentioned in https://www.elastic.co/guide/en/kibana/master/settings.html + +For more information, see <>. +-- diff --git a/x-pack/docs/en/security/securing-kibana.asciidoc b/docs/security/securing-kibana.asciidoc similarity index 69% rename from x-pack/docs/en/security/securing-kibana.asciidoc rename to docs/security/securing-kibana.asciidoc index 706f957fb22860..fba38fa7d6c5d6 100644 --- a/x-pack/docs/en/security/securing-kibana.asciidoc +++ b/docs/security/securing-kibana.asciidoc @@ -40,7 +40,7 @@ APIs and the `.kibana` index. The server does _not_ need access to user indices. The password for the built-in `kibana` user is typically set as part of the {security} configuration process on {es}. For more information, see -{xpack-ref}/setting-up-authentication.html#built-in-users[Built-in Users]. +{stack-ov}/built-in-users.html[Built-in users]. -- . Set the `xpack.security.encryptionKey` property in the `kibana.yml` @@ -69,52 +69,7 @@ xpack.security.sessionTimeout: 600000 -------------------------------------------------------------------------------- -- -[[configure-kibana-cert]] -. Configure {kib} to encrypt communications between the browser and the {kib} -server: - -.. Generate a server certificate for {kib}. You must either set the certificate's -`subjectAltName` to the hostname, fully-qualified domain name (FQDN), or IP -address of the {kib} server, or set the CN to the {kib} server's hostname -or FQDN. Using the server's IP address as the CN does not work. - -.. Set the `server.ssl.key` and `server.ssl.certificate` properties in `kibana.yml`: -+ --- -[source,yaml] --------------------------------------------------------------------------------- -server.ssl.key: /path/to/your/server.key -server.ssl.certificate: /path/to/your/server.crt --------------------------------------------------------------------------------- - -Once you enable SSL encryption between the browser and the {kib} server, -access {kib} via HTTPS. For example, `https://localhost:5601`. --- - -[[configure-kibana-ssl]] -. If you have enabled SSL encryption in {security}, configure {kib} to connect -to {es} via HTTPS: - -.. Specify the HTTPS protocol in the `elasticsearch.url` setting in the {kib} -configuration file, `kibana.yml`: -+ --- -[source,yaml] --------------------------------------------------------------------------------- -elasticsearch.url: "https://.com:9200" --------------------------------------------------------------------------------- --- - -.. If you are using your own CA to sign certificates for {es}, set the -`elasticsearch.ssl.certificateAuthorities` setting in `kibana.yml` to specify -the location of the PEM file. -+ --- -[source,yaml] --------------------------------------------------------------------------------- -elasticsearch.ssl.certificateAuthorities: /path/to/your/cacert.pem --------------------------------------------------------------------------------- --- +. Optional: <>. . Restart {kib}. @@ -168,4 +123,5 @@ NOTE: This must be a user who has been assigned the `kibana_user` role. -- include::authentication/index.asciidoc[] -include::{xkb-repo-dir}/settings/security-settings.asciidoc[] +include::securing-communications/index.asciidoc[] +include::{kib-repo-dir}/settings/security-settings.asciidoc[] diff --git a/x-pack/docs/en/settings/apm-settings.asciidoc b/docs/settings/apm-settings.asciidoc similarity index 76% rename from x-pack/docs/en/settings/apm-settings.asciidoc rename to docs/settings/apm-settings.asciidoc index c733c4993172fe..4f67e7d6dcecdb 100644 --- a/x-pack/docs/en/settings/apm-settings.asciidoc +++ b/docs/settings/apm-settings.asciidoc @@ -11,5 +11,5 @@ You do not need to configure any settings to use APM. It is enabled by default. [[general-apm-settings-kb]] ==== General APM Settings -xpack.apm.ui.enabled:: Set to `false` to hide the APM UI in {kib}. Defaults to +xpack.apm.enabled:: Set to `false` to disabled the APM plugin {kib}. Defaults to `true`. diff --git a/x-pack/docs/en/settings/dev-settings.asciidoc b/docs/settings/dev-settings.asciidoc similarity index 100% rename from x-pack/docs/en/settings/dev-settings.asciidoc rename to docs/settings/dev-settings.asciidoc diff --git a/x-pack/docs/en/settings/graph-settings.asciidoc b/docs/settings/graph-settings.asciidoc similarity index 100% rename from x-pack/docs/en/settings/graph-settings.asciidoc rename to docs/settings/graph-settings.asciidoc diff --git a/x-pack/docs/en/settings/images/monitoring-es-cgroup-true.png b/docs/settings/images/monitoring-es-cgroup-true.png similarity index 100% rename from x-pack/docs/en/settings/images/monitoring-es-cgroup-true.png rename to docs/settings/images/monitoring-es-cgroup-true.png diff --git a/x-pack/docs/en/settings/ml-settings.asciidoc b/docs/settings/ml-settings.asciidoc similarity index 100% rename from x-pack/docs/en/settings/ml-settings.asciidoc rename to docs/settings/ml-settings.asciidoc diff --git a/x-pack/docs/en/settings/monitoring-settings.asciidoc b/docs/settings/monitoring-settings.asciidoc similarity index 100% rename from x-pack/docs/en/settings/monitoring-settings.asciidoc rename to docs/settings/monitoring-settings.asciidoc diff --git a/x-pack/docs/en/settings/reporting-settings.asciidoc b/docs/settings/reporting-settings.asciidoc similarity index 94% rename from x-pack/docs/en/settings/reporting-settings.asciidoc rename to docs/settings/reporting-settings.asciidoc index c17f0283c109f2..ad4de90b0cb461 100644 --- a/x-pack/docs/en/settings/reporting-settings.asciidoc +++ b/docs/settings/reporting-settings.asciidoc @@ -1,6 +1,6 @@ [role="xpack"] [[reporting-settings-kb]] -=== X-Pack Reporting Settings in Kibana +=== {reporting} settings in Kibana ++++ Reporting Settings ++++ @@ -14,7 +14,7 @@ You can configure `xpack.reporting` settings in your `kibana.yml` to: [float] [[general-reporting-settings]] ==== General Reporting Settings -`xpack.reporting.enabled`:: +[[xpack-enable-reporting]]`xpack.reporting.enabled`:: Set to `false` to disable {reporting}. `xpack.reporting.encryptionKey`:: @@ -54,7 +54,7 @@ Valid values are `year`, `month`, `week`, `day`, and `hour`. Defaults to `week`. `xpack.reporting.queue.pollInterval`:: How often idle workers poll the index for pending jobs. Defaults to `3000` (3 seconds). -`xpack.reporting.queue.timeout`:: +[[xpack-reporting-q-timeout]]`xpack.reporting.queue.timeout`:: How long each worker has to produce a report. If your machine is slow or under heavy load, you might need to increase this timeout. Specified in milliseconds. Defaults to `30000` (30 seconds). @@ -73,7 +73,7 @@ setting should not have much effect. If you are seeing empty images instead of visualizations, try increasing this value. Defaults to `3000` (3 seconds). -`xpack.reporting.capture.browser.type`:: +[[xpack-reporting-browser]]`xpack.reporting.capture.browser.type`:: Specifies the browser to use to capture screenshots. Valid options are `phantom` and `chromium`. When `chromium` is set, the settings specified in the <> are respected. @@ -106,7 +106,7 @@ Examples of valid entries are "elastic.co", "*.elastic.co", ".elastic.co", ".ela [float] [[reporting-csv-settings]] ==== CSV Settings -`xpack.reporting.csv.maxSizeBytes`:: +[[xpack-reporting-csv]]`xpack.reporting.csv.maxSizeBytes`:: The maximum size of a CSV file before being truncated. This setting exists to prevent large exports from causing performance and storage issues. Defaults to `10485760` (10mB) diff --git a/x-pack/docs/en/settings/security-settings.asciidoc b/docs/settings/security-settings.asciidoc similarity index 100% rename from x-pack/docs/en/settings/security-settings.asciidoc rename to docs/settings/security-settings.asciidoc diff --git a/x-pack/docs/en/settings/settings-xkb.asciidoc b/docs/settings/settings-xkb.asciidoc similarity index 100% rename from x-pack/docs/en/settings/settings-xkb.asciidoc rename to docs/settings/settings-xkb.asciidoc diff --git a/x-pack/docs/en/settings/ssl-settings.asciidoc b/docs/settings/ssl-settings.asciidoc similarity index 100% rename from x-pack/docs/en/settings/ssl-settings.asciidoc rename to docs/settings/ssl-settings.asciidoc diff --git a/docs/setup/docker.asciidoc b/docs/setup/docker.asciidoc index 933180715eaa0e..4a04b8383239dc 100644 --- a/docs/setup/docker.asciidoc +++ b/docs/setup/docker.asciidoc @@ -7,6 +7,8 @@ A list of all published Docker images and tags can be found at https://www.docker.elastic.co[www.docker.elastic.co]. The source code can be found on https://github.com/elastic/kibana-docker/tree/{branch}[GitHub]. +[float] +[[image-type]] === Image types These images are free to use under the Elastic license. They contain open source @@ -19,6 +21,8 @@ Elastic license levels. Alternatively, you can download `-oss` images, which contain only features that are available under the Apache 2.0 license. +[float] +[[pull-image]] === Pulling the image Obtaining Kibana for Docker is as simple as issuing a +docker pull+ command against the Elastic Docker registry. @@ -42,6 +46,8 @@ docker pull {docker-repo}-oss:{version} endif::[] +[float] +[[configuring-kibana-docker]] === Configuring Kibana on Docker The Docker images provide several methods for configuring Kibana. The @@ -49,7 +55,8 @@ conventional approach is to provide a `kibana.yml` file as described in {kibana-ref}/settings.html[Configuring Kibana], but it's also possible to use environment variables to define settings. -[[docker-bind-mount-config]] +[float] +[[bind-mount-config]] ==== Bind-mounted configuration One way to configure Kibana on Docker is to provide `kibana.yml` via bind-mounting. @@ -65,7 +72,8 @@ services: - ./kibana.yml:/usr/share/kibana/config/kibana.yml -------------------------------------------- -[[docker-env-config]] +[float] +[[environment-variable-config]] ==== Environment variable configuration Under Docker, Kibana can be configured via environment variables. When @@ -87,7 +95,7 @@ Some example translations are shown here: `XPACK_MONITORING_ENABLED`:: `xpack.monitoring.enabled` In general, any setting listed in <> or -{xpack-ref}/xpack-settings.html[X-Pack Settings] can be configured +{xpack-ref}/xpack-settings.html[{xpack} Settings] can be configured with this technique. These variables can be set with +docker-compose+ like this: @@ -106,6 +114,8 @@ services: Since environment variables are translated to CLI arguments, they take precedence over settings configured in `kibana.yml`. +[float] +[[docker-defaults]] ==== Docker defaults The following settings have different default values when using the Docker images: @@ -115,7 +125,7 @@ images: `server.host`:: `"0"` `elasticsearch.url`:: `http://elasticsearch:9200` -In the `x-pack` image, the following additional defaults are also set: +In the {xpack} image, the following additional defaults are also set: [horizontal] `elasticsearch.username`:: `elastic` @@ -123,8 +133,8 @@ In the `x-pack` image, the following additional defaults are also set: `xpack.monitoring.ui.container.elasticsearch.enabled`:: `true` These settings are defined in the default `kibana.yml`. They can be overridden -with a <> or via -<>. +with a <> or via +<>. IMPORTANT: If replacing `kibana.yml` with a custom version, be sure to copy the above defaults to the custom file if you want to retain them. If not, they will diff --git a/docs/setup/install.asciidoc b/docs/setup/install.asciidoc index f596e59d09df8b..ace96b88599638 100644 --- a/docs/setup/install.asciidoc +++ b/docs/setup/install.asciidoc @@ -38,9 +38,10 @@ downloaded from the Elastic Docker Registry. + <> -IMPORTANT: If your Elasticsearch installation is protected by {xpack-ref}/xpack-security.html[X-Pack Security] -see {kibana-ref}/using-kibana-with-security.html[Configuring Security in Kibana] -for additional setup instructions. +IMPORTANT: If your Elasticsearch installation is protected by +{xpack-ref}/xpack-security.html[{security}] see +{kibana-ref}/using-kibana-with-security.html[Configuring Security in Kibana] for +additional setup instructions. include::install/targz.asciidoc[] diff --git a/docs/setup/production.asciidoc b/docs/setup/production.asciidoc index 042b0ff98768e9..db1373f5e5d00b 100644 --- a/docs/setup/production.asciidoc +++ b/docs/setup/production.asciidoc @@ -1,9 +1,9 @@ [[production]] -== Using Kibana in a Production Environment +== Using Kibana in a production environment -* <> +* <> * <> -* <> +* <> How you deploy Kibana largely depends on your use case. If you are the only user, you can run Kibana on your local machine and configure it to point to whatever @@ -19,63 +19,28 @@ and an Elasticsearch client node on the same machine. For more information, see [float] [[configuring-kibana-shield]] -=== Using Kibana with X-Pack +=== Using Kibana with {security} -You can use {xpack-ref}/xpack-security.html[X-Pack Security] to control what +You can use {stack-ov}/xpack-security.html[{security}] to control what Elasticsearch data users can access through Kibana. -When you install X-Pack, Kibana users have to log in. They need to +When {security} is enabled, Kibana users have to log in. They need to have the `kibana_user` role as well as access to the indices they will be working with in Kibana. If a user loads a Kibana dashboard that accesses data in an index that they are not authorized to view, they get an error that indicates the index does -not exist. X-Pack Security does not currently provide a way to control which +not exist. {security} does not currently provide a way to control which users can load which dashboards. -For information about setting up Kibana users and how to configure Kibana -to work with X-Pack, see -{kibana-ref}/using-kibana-with-security.html[Configuring Security in Kibana]. +For information about setting up Kibana users, see +{kibana-ref}/using-kibana-with-security.html[Configuring security in Kibana]. [float] [[enabling-ssl]] === Enabling SSL -Kibana supports SSL encryption for both client requests and the requests the Kibana server -sends to Elasticsearch. -To encrypt communications between the browser and the Kibana server, you configure the `server.ssl.enabled`, -`server.ssl.certificate` and `server.ssl.key` properties in `kibana.yml`: - -[source,text] ----- -# SSL for outgoing requests from the Kibana Server (PEM formatted) -server.ssl.enabled: true -server.ssl.key: /path/to/your/server.key -server.ssl.certificate: /path/to/your/server.crt ----- - -If you are using X-Pack Security or a proxy that provides an HTTPS endpoint for Elasticsearch, -you can configure Kibana to access Elasticsearch via HTTPS so communications between -the Kibana server and Elasticsearch are encrypted. - -To do this, you specify the HTTPS -protocol when you configure the Elasticsearch URL in `kibana.yml`: - -[source,text] ----- -elasticsearch.url: "https://.com:9200" ----- - -If you are using a self-signed certificate for Elasticsearch, set the `certificateAuthorities` property in -`kibana.yml` to specify the location of the PEM file. Setting the `certificateAuthorities` property lets you use the -default `verificationMode` option of `full`. - -[source,text] ----- -# If you need to provide a CA certificate for your Elasticsearch instance, put -# the path of the pem file here. -elasticsearch.ssl.certificateAuthorities: [ "/path/to/your/ca/cacert.pem" ] ----- +See <>. [float] [[load-balancing]] diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index ba6d584d8b4873..9750a0af3a5846 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -3,51 +3,70 @@ The Kibana server reads properties from the `kibana.yml` file on startup. The default settings configure Kibana to run on `localhost:5601`. To change the host or port number, or connect to Elasticsearch running on a different machine, -you'll need to update your `kibana.yml` file. You can also enable SSL and set a variety of other options. +you'll need to update your `kibana.yml` file. You can also enable SSL and set a variety of other options. Finally, environment variables can be injected into configuration using `${MY_ENV_VAR}` syntax. .Kibana Configuration Settings + `console.enabled:`:: *Default: true* Set to false to disable Console. Toggling this will cause the server to regenerate assets on the next startup, which may cause a delay before pages start being served. `cpu.cgroup.path.override:`:: Override for cgroup cpu path when mounted in manner that is inconsistent with `/proc/self/cgroup` + `cpuacct.cgroup.path.override:`:: Override for cgroup cpuacct path when mounted in manner that is inconsistent with `/proc/self/cgroup` `elasticsearch.customHeaders:`:: *Default: `{}`* Header names and values to send to Elasticsearch. Any custom headers cannot be overwritten by client-side headers, regardless of the `elasticsearch.requestHeadersWhitelist` configuration. + +`elasticsearch.logQueries:`:: *Default: `false`* Logs queries sent to Elasticsearch. Requires `logging.verbose` set to `true`. This is useful for seeing the query DSL generated by applications that currently do not have a spy panel, for example Timelion and Monitoring. + `elasticsearch.pingTimeout:`:: *Default: the value of the `elasticsearch.requestTimeout` setting* Time in milliseconds to wait for Elasticsearch to respond to pings. + `elasticsearch.preserveHost:`:: *Default: true* When this setting’s value is true Kibana uses the hostname specified in the `server.host` setting. When the value of this setting is `false`, Kibana uses the hostname of the host that connects to this Kibana instance. + `elasticsearch.requestHeadersWhitelist:`:: *Default: `[ 'authorization' ]`* List of Kibana client-side headers to send to Elasticsearch. To send *no* client-side headers, set this value to [] (an empty list). + `elasticsearch.requestTimeout:`:: *Default: 30000* Time in milliseconds to wait for responses from the back end or Elasticsearch. This value must be a positive integer. + `elasticsearch.shardTimeout:`:: *Default: 30000* Time in milliseconds for Elasticsearch to wait for responses from shards. Set to 0 to disable. + `elasticsearch.ssl.certificate:` and `elasticsearch.ssl.key:`:: Optional settings that provide the paths to the PEM-format SSL certificate and key files. These files are used to verify the identity of Kibana to Elasticsearch and are required when `xpack.ssl.verification_mode` in Elasticsearch is set to either `certificate` or `full`. -`elasticsearch.ssl.certificateAuthorities:`:: Optional setting that enables you to specify a list of paths to the PEM file for the certificate -authority for your Elasticsearch instance. + +`elasticsearch.ssl.certificateAuthorities:`:: Optional setting that enables you to specify a list of paths to the PEM file for the certificate authority for your Elasticsearch instance. + `elasticsearch.ssl.keyPassphrase:`:: The passphrase that will be used to decrypt the private key. This value is optional as the key may not be encrypted. + `elasticsearch.ssl.verificationMode:`:: *Default: full* Controls the verification of certificates presented by Elasticsearch. Valid values are `none`, `certificate`, and `full`. `full` performs hostname verification, and `certificate` does not. + `elasticsearch.startupTimeout:`:: *Default: 5000* Time in milliseconds to wait for Elasticsearch at Kibana startup before retrying. + `elasticsearch.url:`:: *Default: "http://localhost:9200"* The URL of the Elasticsearch instance to use for all your queries. + `elasticsearch.username:` and `elasticsearch.password:`:: If your Elasticsearch is protected with basic authentication, these settings provide the username and password that the Kibana server uses to perform maintenance on the Kibana index at startup. Your Kibana users still need to authenticate with Elasticsearch, which is proxied through the Kibana server. `kibana.defaultAppId:`:: *Default: "discover"* The default application to load. + `kibana.index:`:: *Default: ".kibana"* Kibana uses an index in Elasticsearch to store saved searches, visualizations and dashboards. Kibana creates a new index if the index doesn’t already exist. `logging.dest:`:: *Default: `stdout`* Enables you specify a file where Kibana stores log output. + `logging.quiet:`:: *Default: false* Set the value of this setting to `true` to suppress all logging output other than error messages. + `logging.silent:`:: *Default: false* Set the value of this setting to `true` to suppress all logging output. -`logging.verbose:`:: *Default: false* Set the value of this setting to `true` to log all events, including system usage -information and all requests. + +[[logging-verbose]]`logging.verbose:`:: *Default: false* Set the value of this setting to `true` to log all events, including system usage information and all requests. Supported on Elastic Cloud Enterprise. + `logging.useUTC`:: *Default: true* Set the value of this setting to `false` to log events using the timezone of the server, rather than UTC. `map.includeElasticMapsService:`:: *Default: true* Turns on or off whether layers from the Elastic Maps Service should be included in the vector and tile layer option list. @@ -60,7 +79,7 @@ By turning this off, only the layers that are configured here will be included. `ops.interval:`:: *Default: 5000* Set the interval in milliseconds to sample system and process performance metrics. The minimum value is 100. -[[regionmap-settings]] `regionmap:`:: Specifies additional vector layers for use in <> visualizations. +[[regionmap-settings]] `regionmap:`:: Specifies additional vector layers for use in <> visualizations. Supported on Elastic Cloud Enterprise. Each layer object points to an external vector file that contains a geojson FeatureCollection. The file must use the https://en.wikipedia.org/wiki/World_Geodetic_System[WGS84 coordinate reference system] and only include polygons. If the file is hosted on a separate domain from Kibana, the server needs to be CORS-enabled so Kibana can download the file. @@ -78,38 +97,62 @@ The following example shows a valid regionmap configuration. - name: "INSEE" description: "INSEE numeric identifier" -`regionmap.layers[].name:`:: Mandatory. A description of the map being provided. -`regionmap.layers[].url:`:: Mandatory. The location of the geojson file as provided by a webserver. -`regionmap.layers[].attribution:`:: Optional. References the originating source of the geojson file. -`regionmap.layers[].fields[]:`:: Mandatory. Each layer can contain multiple fields to indicate what properties from the geojson features you wish to expose. The example above shows how to define multiple properties. -`regionmap.layers[].fields[].name:`:: Mandatory. This value is used to do an inner-join between the document stored in Elasticsearch and the geojson file. e.g. if the field in the geojson is called `Location` and has city names, there must be a field in Elasticsearch that holds the same values that Kibana can then use to lookup for the geoshape data. -`regionmap.layers[].fields[].description:`:: Mandatory. The human readable text that is shown under the Options tab when building the Region Map visualization. -`regionmap.includeElasticMapsService:`:: *Default: true* Turns on or off whether layers from the Elastic Maps Service should be included in the vector layer option list. -By turning this off, only the layers that are configured here will be included. +[[regionmap-name]]`regionmap.layers[].name:`:: Mandatory. A description of the map being provided. Supported on Elastic Cloud Enterprise. + +[[regionmap-url]]`regionmap.layers[].url:`:: Mandatory. The location of the geojson file as provided by a webserver. Supported on Elastic Cloud Enterprise. + +[[regionmap-attribution]]`regionmap.layers[].attribution:`:: Optional. References the originating source of the geojson file. Supported on Elastic Cloud Enterprise. + +[[regionmap-fields]]`regionmap.layers[].fields[]:`:: Mandatory. Each layer can contain multiple fields to indicate what properties from the geojson features you wish to expose. The example above shows how to define multiple properties. Supported on Elastic Cloud Enterprise. + +[[regionmap-field-name]]`regionmap.layers[].fields[].name:`:: Mandatory. This value is used to do an inner-join between the document stored in Elasticsearch and the geojson file. e.g. if the field in the geojson is called `Location` and has city names, there must be a field in Elasticsearch that holds the same values that Kibana can then use to lookup for the geoshape data. Supported on Elastic Cloud Enterprise. + +[[regionmap-field-description]]`regionmap.layers[].fields[].description:`:: Mandatory. The human readable text that is shown under the Options tab when building the Region Map visualization. Supported on Elastic Cloud Enterprise. + +[[regionmap-ES-map]]`regionmap.includeElasticMapsService:`:: turns on or off whether layers from the Elastic Maps Service should be included in the vector layer option list. Supported on Elastic Cloud Enterprise. +By turning this off, only the layers that are configured here will be included. The default is true. `server.basePath:`:: Enables you to specify a path to mount Kibana at if you are running behind a proxy. Use the `server.rewriteBasePath` setting to tell Kibana if it should remove the basePath from requests it receives, and to prevent a deprecation warning at startup. This setting cannot end in a slash (`/`). + `server.rewriteBasePath:`:: *Default: false* Specifies whether Kibana should rewrite requests that are prefixed with `server.basePath` or require that they are rewritten by your reverse proxy. This setting was effectively always `false` before Kibana 6.3 and will default to `true` starting in Kibana 7.0. + `server.customResponseHeaders:`:: *Default: `{}`* Header names and values to send on all responses to the client from the Kibana server. -`server.defaultRoute:`:: *Default: "/app/kibana"* This setting specifies the default route when opening Kibana. You can use this setting to modify the landing page when opening Kibana. + +[[server-default]]`server.defaultRoute:`:: *Default: "/app/kibana"* This setting specifies the default route when opening Kibana. You can use this setting to modify the landing page when opening Kibana. Supported on Elastic Cloud Enterprise. + `server.host:`:: *Default: "localhost"* This setting specifies the host of the back end server. + `server.maxPayloadBytes:`:: *Default: 1048576* The maximum payload size in bytes for incoming server requests. + `server.name:`:: *Default: "your-hostname"* A human-readable display name that identifies this Kibana instance. + `server.port:`:: *Default: 5601* Kibana is served by a back end server. This setting specifies the port to use. + `server.ssl.enabled:`:: *Default: "false"* Enables SSL for outgoing requests from the Kibana server to the browser. When set to `true`, `server.ssl.certificate` and `server.ssl.key` are required + `server.ssl.certificate:` and `server.ssl.key:`:: Paths to the PEM-format SSL certificate and SSL key files, respectively. + `server.ssl.certificateAuthorities:`:: List of paths to PEM encoded certificate files that should be trusted. + `server.ssl.cipherSuites:`:: *Default: ECDHE-RSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-ECDSA-AES256-GCM-SHA384, DHE-RSA-AES128-GCM-SHA256, ECDHE-RSA-AES128-SHA256, DHE-RSA-AES128-SHA256, ECDHE-RSA-AES256-SHA384, DHE-RSA-AES256-SHA384, ECDHE-RSA-AES256-SHA256, DHE-RSA-AES256-SHA256, HIGH,!aNULL, !eNULL, !EXPORT, !DES, !RC4, !MD5, !PSK, !SRP, !CAMELLIA*. Details on the format, and the valid options, are available via the [OpenSSL cipher list format documentation](https://www.openssl.org/docs/man1.0.2/apps/ciphers.html#CIPHER-LIST-FORMAT) + `server.ssl.keyPassphrase:`:: The passphrase that will be used to decrypt the private key. This value is optional as the key may not be encrypted. + `server.ssl.redirectHttpFromPort:`:: Kibana will bind to this port and redirect all http requests to https over the port configured as `server.port`. + `server.ssl.supportedProtocols:`:: *Default: TLSv1, TLSv1.1, TLSv1.2* Supported protocols with versions. Valid protocols: `TLSv1`, `TLSv1.1`, `TLSv1.2` `status.allowAnonymous:`:: *Default: false* If authentication is enabled, setting this to `true` allows unauthenticated users to access the Kibana server status API and status page. -[[tilemap-settings]] `tilemap.options.attribution:`:: *Default: `"© [Elastic Maps Service](https://www.elastic.co/elastic-maps-service)"`* The map attribution string. -`tilemap.options.maxZoom:`:: *Default: 10* The maximum zoom level. -`tilemap.options.minZoom:`:: *Default: 1* The minimum zoom level. -`tilemap.options.subdomains:`:: An array of subdomains used by the tile service. -Specify the position of the subdomain the URL with the token `{s}`. -`tilemap.url:`:: The URL to the tileservice that Kibana uses to display map tiles in tilemap visualizations. By default, Kibana reads this url from an external metadata service, but users can still override this parameter to use their own Tile Map Service. For example: `"https://tiles.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana"` -`vega.enableExternalUrls:`:: *Default: false* Set this value to true to allow Vega to use any URL to access external data sources and images. If false, Vega can only get data from Elasticsearch. +[[tilemap-settings]] `tilemap.options.attribution:`:: *Default: `"© [Elastic Maps Service](https://www.elastic.co/elastic-maps-service)"`* The map attribution string. Supported on Elastic Cloud Enterprise. + +[[tilemap-max-zoom]]`tilemap.options.maxZoom:`:: *Default: 10* The maximum zoom level. Supported on Elastic Cloud Enterprise. + +[[tilemap-min-zoom]]`tilemap.options.minZoom:`:: *Default: 1* The minimum zoom level. Supported on Elastic Cloud Enterprise. + +[[tilemap-subdomains]]`tilemap.options.subdomains:`:: An array of subdomains used by the tile service. +Specify the position of the subdomain the URL with the token `{s}`. Supported on Elastic Cloud Enterprise. + +[[tilemap-url]]`tilemap.url:`:: The URL to the tileservice that Kibana uses to display map tiles in tilemap visualizations. Supported on Elastic Cloud Enterprise. +By default, Kibana reads this url from an external metadata service, but users can still override this parameter to use their own Tile Map Service. For example: `"https://tiles.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana"` diff --git a/x-pack/docs/en/setup/setup-xkb.asciidoc b/docs/setup/setup-xkb.asciidoc similarity index 82% rename from x-pack/docs/en/setup/setup-xkb.asciidoc rename to docs/setup/setup-xkb.asciidoc index 7e2a24f491c3c3..75ac801955c78f 100644 --- a/x-pack/docs/en/setup/setup-xkb.asciidoc +++ b/docs/setup/setup-xkb.asciidoc @@ -1,9 +1,7 @@ [role="xpack"] [[setup-xpack-kb]] -= Set Up X-Pack +== Set Up {xpack} -[partintro] --- {xpack} is an Elastic Stack extension that provides security, alerting, monitoring, reporting, machine learning, graph, and many other capabilities. By default, when you install {kib}, {xpack} is installed. @@ -26,8 +24,4 @@ The **Management** page gains options related to configuring security. The other {xpack} features are mentioned in this documentation, we've added an icon to clearly indicate that what you're reading pertains to features available only in {xpack}. --- -include::{xkb-repo-dir}/monitoring/monitoring-xkib.asciidoc[] -include::{xkb-repo-dir}/security/securing-kibana.asciidoc[] -include::{xkb-repo-dir}/settings/settings-xkb.asciidoc[] diff --git a/docs/visualize.asciidoc b/docs/visualize.asciidoc index 31656f727b0183..d955c7753a9307 100644 --- a/docs/visualize.asciidoc +++ b/docs/visualize.asciidoc @@ -47,9 +47,10 @@ data sets. <>:: Visualize time series data using pipeline aggregations. * *Other* [horizontal] -<>:: Display words as a cloud in which the size of the word correspond to its importance +<>:: Controls provide the ability to add interactive inputs to Kibana Dashboards. <>:: Display free-form information or instructions. +<>:: Display words as a cloud in which the size of the word correspond to its importance. <>:: Support for user-defined graphs, external data sources, images, and user-defined interactivity. . Specify a search query to retrieve the data for your visualization: ** To enter new search criteria, select the index pattern for the indices that @@ -139,6 +140,8 @@ Aggregation Execution Order, and You]. include::visualize/xychart.asciidoc[] +include::visualize/controls.asciidoc[] + include::visualize/datatable.asciidoc[] include::visualize/markdown.asciidoc[] diff --git a/docs/visualize/controls.asciidoc b/docs/visualize/controls.asciidoc new file mode 100644 index 00000000000000..f138044d788ef0 --- /dev/null +++ b/docs/visualize/controls.asciidoc @@ -0,0 +1,95 @@ +[[controls]] +== Controls Visualization +experimental[] + + +The Controls visualization enables you to add interactive inputs +to Kibana dashboards. You can create two types of inputs: +a dropdown menu and a radio slider. + +[role="screenshot"] +image::images/controls/controls_in_dashboard.png[] + +[[add-input-controls]] +=== Adding Input Controls + +To start a *Controls* visualization, open the Visualization application +and click the *+* button. Scroll to the *Others* section and +select *Controls*. + +In the visualization builder, choose the type of control to add to +your visualization. + +==== Dropdown menu + +A dropdown menu allows users to filter content by selecting +one or more options from a list. The dropdown menu is dynamically populated +with the results of a terms aggregation. + +[role="screenshot"] +image::images/controls/dropdown_control_editor.png[] + +*Control Label*:: The label for the dropdown menu. By default, the +label is the field name. + +*Index Pattern*:: The <> that contains +the data set to visualize. + +*Field*:: The field used to populate the list of options +and filter on when users interact with the input. +The list of available fields is derived from the specified +index pattern. + +*Parent control*:: The control for chaining dropdown menus so that the +selection in the first menu +filters the terms in the second menu. Only available when +creating multiple dropdown menus. + +*Multiselect*:: When enabled, the dropdown menu allows users to select multiple options. + +*Size*:: The number of options to include in the list. + +==== Range slider + +A range sliders allow users to filter content within a range of numbers. +The range slider minimum and maximum values are dynamically populated with +the results of a min and max aggregation. + +[role="screenshot"] +image::images/controls/range_slider_editor.png[] + +*Control Label*:: The label for the range slider. By default, the +label is the field name. + +*Index Pattern*:: The <> that contains +the data set to visualize. + +*Field*:: The field used to populate the range slider +and filter on when users interact with the input. +The list of available fields is derived from the +specified index pattern. + +*Step Size*:: The increment/decrement size of the slider. + +*Decimal Places*:: The number of decimal places. + +[[global-options]] +=== Global Options + +Open the *Options* tab to configure settings that apply to all input +controls in a Controls visualization. + +[role="screenshot"] +image::images/controls/controls_options.png[] + +*Update Kibana filters on each change*:: When enabled, all input interactions +immediately create filters that cause the dashboard to refresh. When disabled, +Kibana filters are only created +when the user clicks *Apply changes* image:images/apply-changes-button.png[]. + +*Use time filter*:: When enabled, the aggregations used to generate +the dropdown options list and range minimum and maximum are bound +to <>. + +*Pin filters to global state*:: When enabled, all filters created by +interacting with the inputs are automatically pinned. diff --git a/docs/visualize/tilemap.asciidoc b/docs/visualize/tilemap.asciidoc index e838337192a7c8..d6333fcc2931fa 100644 --- a/docs/visualize/tilemap.asciidoc +++ b/docs/visualize/tilemap.asciidoc @@ -7,10 +7,14 @@ NOTE: By default, Kibana uses the https://www.elastic.co/elastic-maps-service[El to display map tiles. To use other tile service providers, configure the <> in `kibana.yml`. +[float] +[[configuration]] === Configuration +[float] ==== Data +[float] ===== Metrics The default _metrics_ aggregation for a coordinate map is the *Count* aggregation. You can select any of the following @@ -31,6 +35,7 @@ the number of unique values in a field. Select a field from the drop-down. Enter a string in the *Custom Label* field to change the display label. +[float] ===== Buckets Coordinate maps use the {ref}/search-aggregations-bucket-geohashgrid-aggregation.html[_geohash_] aggregation. Select a field, typically coordinates, from the @@ -66,6 +71,7 @@ NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you The availability of these options varies depending on the aggregation you choose. +[float] ==== Options @@ -98,8 +104,7 @@ After changing options, click the *Apply changes* button to update your visuali changes* button to keep your visualization in its current state. [float] -[[navigating-map]] - +[[navigate-map]] === Navigating the Map Once your tilemap visualization is ready, you can explore the map in several ways: diff --git a/docs/visualize/time-series-visual-builder.asciidoc b/docs/visualize/time-series-visual-builder.asciidoc index a385dcf92605b0..59c319851589d1 100644 --- a/docs/visualize/time-series-visual-builder.asciidoc +++ b/docs/visualize/time-series-visual-builder.asciidoc @@ -10,9 +10,10 @@ aggregations and pipeline aggregations to display complex data in a meaningful w image:images/tsvb-screenshot.png["Time Series Visual Builder Interface"] +[[time-series-visualizations]] === Featured Visualizations -Time Series Visual Build comes with 5 different visualization types. You can +Time Series Visual Build comes with 6 different visualization types. You can switch between each visualization type using the tabbed picker at the top of the interface. @@ -65,6 +66,15 @@ template syntax to customize the Markdown with data based on a set of series. image:images/tsvb-markdown.png["Markdown Visualization"] +==== Table + +A table visualization allows you to display data from multiple time series. +You define which field group to show in the rows and what columns of data to display. + +image:images/tsvb-table.png["Table Visualization"] + + +[[time-series-interface]] === Interface Overview The user interface for each visualization is compose of a "Data" tab and "Panel diff --git a/docs/visualize/xychart.asciidoc b/docs/visualize/xychart.asciidoc index ce77fc221f8ab1..dd8e0c33ecd92e 100644 --- a/docs/visualize/xychart.asciidoc +++ b/docs/visualize/xychart.asciidoc @@ -33,11 +33,14 @@ NOTE: In Elasticsearch releases 1.4.3 and later, this functionality requires you The availability of these options varies depending on the aggregation you choose. +[float] +[[metrics-axes]] === Metrics & Axes Select the *Metrics & Axes* tab to change the way each individual metric is shown on the chart. The data series are styled in the _Metrics_ section, while the axes are styled in the X and Y axis sections. +[float] ==== Metrics Modify how each metric from the Data panel is visualized on the chart. @@ -46,6 +49,7 @@ Modify how each metric from the Data panel is visualized on the chart. *Value Axis*:: choose the axis you want to plot this data too (the properties of each are configured under Y-axes). *Line mode*:: should the outline of lines or bars appear *smooth*, *straight*, or *stepped*. +[float] ==== Y-axis Style all the Y-axes of the chart. @@ -61,6 +65,7 @@ Style all the Y-axes of the chart. this box to change both upper and lower bounds to match the values returned in the data. *Custom Extents*:::: You can define custom minimum and maximum for each axis +[float] ==== X-Axis *Position*:: position of the X-Axis (*left* or *right* for horizontal charts, and *top* or *bottom* for vertical charts). @@ -70,16 +75,19 @@ Style all the Y-axes of the chart. *Labels - Rotate*:::: You can enter the number in degrees for how much you want to rotate labels *Labels - Truncate*:::: You can enter the size in pixels to which the label is truncated - +[float] +[[panel-settings]] === Panel Settings These are options that apply to the entire chart and not just the individual data series. +[float] ==== Common options *Legend Position*:: Move your legend to the *left*, *right*, *top* or *bottom* *Show Tooltip*:: Enables or disables the display of tooltip on hovering over chart objects *Current Time Marker*:: Show a line indicating the current time +[float] ==== Grid options You can enable grid on the chart. By default grid is displayed on the category axis only. diff --git a/package.json b/package.json index d6b4e7fc5142b9..09fa30bb9d02c8 100644 --- a/package.json +++ b/package.json @@ -57,11 +57,12 @@ "checkLicenses": "grunt licenses", "build": "node scripts/build", "start": "node scripts/kibana --dev", - "debug": "node --nolazy --inspect --debug-brk scripts/kibana --dev", + "debug": "node --nolazy --inspect scripts/kibana --dev", + "debug-break": "node --nolazy --inspect-brk scripts/kibana --dev", "precommit": "node scripts/precommit_hook", "karma": "karma start", - "lint": "echo 'use `node scripts/eslint`' && false", - "lintroller": "echo 'use `node scripts/eslint --fix`' && false", + "lint": "echo 'use `node scripts/eslint` and/or `node scripts/tslint`' && false", + "lintroller": "echo 'use `node scripts/eslint --fix` and/or `node scripts/tslint --fix`' && false", "makelogs": "echo 'use `node scripts/makelogs`' && false", "mocha": "echo 'use `node scripts/mocha`' && false", "sterilize": "grunt sterilize", @@ -76,7 +77,7 @@ "url": "https://github.com/elastic/kibana.git" }, "dependencies": { - "@elastic/eui": "v0.0.38", + "@elastic/eui": "v0.0.49", "@elastic/filesaver": "1.1.2", "@elastic/numeral": "2.3.2", "@elastic/ui-ace": "0.2.3", @@ -102,7 +103,7 @@ "bluebird": "2.9.34", "body-parser": "1.12.0", "boom": "5.2.0", - "brace": "0.10.0", + "brace": "0.11.1", "bunyan": "1.7.1", "cache-loader": "1.0.3", "chalk": "2.3.0", @@ -119,8 +120,10 @@ "elasticsearch-browser": "^14.2.1", "encode-uri-query": "1.0.0", "even-better": "7.0.2", + "execa": "^0.10.0", "expiry-js": "0.1.7", "extract-text-webpack-plugin": "3.0.1", + "fetch-mock": "^5.13.1", "file-loader": "1.1.4", "font-awesome": "4.4.0", "glob": "5.0.13", @@ -130,8 +133,8 @@ "handlebars": "4.0.5", "hapi": "14.2.0", "hjson": "3.1.0", - "http-proxy-agent": "1.0.0", - "https-proxy-agent": "2.1.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", "inert": "4.0.2", "jade": "1.11.0", "jade-loader": "0.8.0", @@ -144,13 +147,13 @@ "leaflet": "1.0.3", "leaflet-draw": "0.4.10", "leaflet-responsive-popup": "0.2.0", - "leaflet-vega": "0.8.3", + "leaflet-vega": "^0.8.6", "leaflet.heat": "0.2.0", "less": "2.7.1", "less-loader": "4.0.5", "lodash": "3.10.1", "lru-cache": "4.1.1", - "markdown-it": "8.3.2", + "markdown-it": "^8.4.1", "minimatch": "2.0.10", "mkdirp": "0.5.1", "moment": "^2.20.1", @@ -165,17 +168,16 @@ "proxy-from-env": "1.0.0", "querystring-browser": "1.0.4", "raw-loader": "0.5.1", - "react": "^16.2.0", + "react": "^16.3.0", "react-addons-shallow-compare": "15.6.2", "react-anything-sortable": "^1.7.4", "react-color": "^2.13.8", - "react-dom": "^16.2.0", + "react-dom": "^16.3.0", "react-grid-layout": "^0.16.2", "react-input-range": "^1.3.0", "react-markdown": "^3.1.4", "react-redux": "^5.0.6", "react-router-dom": "4.2.2", - "react-select": "^1.2.0", "react-sizeme": "^2.3.6", "react-toggle": "4.0.2", "reactcss": "1.2.3", @@ -190,7 +192,7 @@ "rison-node": "1.0.0", "rxjs": "5.4.3", "script-loader": "0.7.2", - "semver": "5.1.0", + "semver": "^5.5.0", "style-loader": "0.19.0", "tar": "2.2.0", "tinygradient": "0.3.0", @@ -202,10 +204,12 @@ "ui-select": "0.19.6", "url-loader": "0.5.9", "uuid": "3.0.1", + "val-loader": "^1.1.0", "validate-npm-package-name": "2.2.2", - "vega-lib": "^3.2.1", - "vega-lite": "^2.3.1", + "vega-lib": "^3.3.1", + "vega-lite": "^2.4.0", "vega-schema-url-parser": "1.0.0", + "vega-tooltip": "^0.9.14", "vision": "4.1.0", "webpack": "3.6.0", "webpack-merge": "4.1.0", @@ -221,12 +225,21 @@ "@kbn/eslint-import-resolver-kibana": "link:packages/kbn-eslint-import-resolver-kibana", "@kbn/eslint-plugin-license-header": "link:packages/kbn-eslint-plugin-license-header", "@kbn/plugin-generator": "link:packages/kbn-plugin-generator", + "@kbn/test": "link:packages/kbn-test", + "@types/eslint": "^4.16.2", + "@types/execa": "^0.9.0", + "@types/getopts": "^2.0.0", + "@types/glob": "^5.0.35", + "@types/listr": "^0.13.0", + "@types/minimatch": "^2.0.29", + "@types/react": "^16.3.14", + "@types/react-dom": "^16.0.5", "angular-mocks": "1.4.7", "babel-eslint": "8.1.2", "babel-jest": "^22.4.3", "backport": "2.2.0", "chai": "3.5.0", - "chance": "1.0.6", + "chance": "1.0.10", "cheerio": "0.22.0", "chokidar": "1.6.0", "chromedriver": "2.36", @@ -234,14 +247,14 @@ "dedent": "^0.7.0", "enzyme": "3.2.0", "enzyme-adapter-react-16": "^1.1.1", - "enzyme-to-json": "3.3.0", + "enzyme-to-json": "3.3.1", "eslint": "4.14.0", "eslint-config-prettier": "^2.9.0", "eslint-plugin-babel": "4.1.2", "eslint-plugin-import": "2.8.0", "eslint-plugin-jest": "^21.6.2", "eslint-plugin-mocha": "4.11.0", - "eslint-plugin-no-unsanitized": "^2.0.2", + "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "1.2.1", "eslint-plugin-prettier": "^2.6.0", "eslint-plugin-react": "7.5.1", @@ -250,14 +263,13 @@ "faker": "1.1.0", "geckodriver": "1.11.0", "getopts": "2.0.0", - "globby": "^8.0.0", + "globby": "^8.0.1", "grunt": "1.0.1", "grunt-cli": "0.1.13", "grunt-contrib-watch": "^1.0.0", "grunt-karma": "2.0.0", "grunt-peg": "^2.0.1", "grunt-run": "0.7.0", - "grunt-simple-mocha": "0.4.0", "gulp-babel": "^7.0.1", "gulp-sourcemaps": "1.7.3", "husky": "0.8.1", @@ -277,6 +289,7 @@ "karma-safari-launcher": "1.0.0", "leadfoot": "1.7.5", "license-checker": "^16.0.0", + "listr": "^0.14.1", "load-grunt-config": "0.19.2", "makelogs": "^4.0.5", "marked-text-renderer": "0.1.0", @@ -287,19 +300,24 @@ "nock": "8.0.0", "pixelmatch": "4.0.2", "prettier": "^1.12.1", - "proxyquire": "1.7.10", + "proxyquire": "1.7.11", "simple-git": "1.37.0", - "sinon": "1.17.2", + "sinon": "^5.0.7", "source-map": "0.5.6", "source-map-support": "0.2.10", "strip-ansi": "^3.0.1", "supertest": "3.0.0", - "supertest-as-promised": "2.0.2", - "tree-kill": "1.1.0", - "ts-jest": "^22.4.3", - "typescript": "^2.8.1", + "supertest-as-promised": "4.0.2", + "tree-kill": "^1.1.0", + "ts-jest": "^22.4.6", + "ts-loader": "^3.5.0", + "ts-node": "^6.0.3", + "tslint": "^5.10.0", + "tslint-config-prettier": "^1.12.0", + "tslint-plugin-prettier": "^1.3.0", + "typescript": "^2.8.3", "vinyl-fs": "^3.0.2", - "xml2js": "0.4.19", + "xml2js": "^0.4.19", "xmlbuilder": "9.0.4" }, "engines": { diff --git a/packages/README.md b/packages/README.md index 3e1881c66bb421..e5111f39892dba 100644 --- a/packages/README.md +++ b/packages/README.md @@ -51,7 +51,7 @@ Today a package can follow the pattern of having a `__tests__` directory in each If a package's tests should be run with Mocha, you'll have to opt-in to run them by appending the package's test file pattern(s) to Kibana's `tasks/config/simplemocha.js` file. These will then be run by the unit test runner. * `yarn test` or `yarn grunt test` runs all unit tests. -* `yarn grunt simplemocha:all` runs all Mocha tests. +* `node scripts/mocha` runs all Mocha tests. ### 2. Jest A package can also follow the pattern of having `.test.js` files as siblings of the source code files, and these run by Jest. diff --git a/packages/eslint-config-kibana/.eslintrc.js b/packages/eslint-config-kibana/.eslintrc.js index 64c7e820accd04..7eb74ca1fce8bc 100644 --- a/packages/eslint-config-kibana/.eslintrc.js +++ b/packages/eslint-config-kibana/.eslintrc.js @@ -118,8 +118,6 @@ module.exports = { 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'], 'react/jsx-equals-spacing': ['error', 'never'], 'react/jsx-indent': ['error', 2], - 'react/no-did-mount-set-state': 'error', - 'react/no-did-update-set-state': 'error', 'react/no-will-update-set-state': 'error', 'react/no-is-mounted': 'error', 'react/no-multi-comp': ['error', { ignoreStateless: true }], diff --git a/packages/eslint-config-kibana/package.json b/packages/eslint-config-kibana/package.json index 303ecb39f35b88..0c04ea50a4c06a 100644 --- a/packages/eslint-config-kibana/package.json +++ b/packages/eslint-config-kibana/package.json @@ -21,7 +21,7 @@ "eslint-plugin-import": "^2.6.0", "eslint-plugin-jest": "^21.0.0", "eslint-plugin-mocha": "^4.9.0", - "eslint-plugin-no-unsanitized": "^2.0.2", + "eslint-plugin-no-unsanitized": "^3.0.2", "eslint-plugin-prefer-object-spread": "^1.2.1", "eslint-plugin-react": "^7.1.0" } diff --git a/packages/kbn-babel-preset/common.js b/packages/kbn-babel-preset/common.js deleted file mode 100644 index a792f5d47e298f..00000000000000 --- a/packages/kbn-babel-preset/common.js +++ /dev/null @@ -1,19 +0,0 @@ -module.exports = { - presets: [ - require.resolve('babel-preset-react'), - ], - plugins: [ - require.resolve('babel-plugin-add-module-exports'), - // stage 3 - require.resolve('babel-plugin-transform-async-generator-functions'), - require.resolve('babel-plugin-transform-object-rest-spread'), - - // the class properties proposal was merged with the private fields proposal - // into the "class fields" proposal. Babel doesn't support this combined - // proposal yet, which includes private field, so this transform is - // TECHNICALLY stage 2, but for all intents and purposes it's stage 3 - // - // See https://github.com/babel/proposals/issues/12 for progress - require.resolve('babel-plugin-transform-class-properties'), - ], -}; diff --git a/packages/kbn-babel-preset/common_preset.js b/packages/kbn-babel-preset/common_preset.js new file mode 100644 index 00000000000000..a2d4495adc54b8 --- /dev/null +++ b/packages/kbn-babel-preset/common_preset.js @@ -0,0 +1,38 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +module.exports = { + presets: [ + require.resolve('babel-preset-react'), + ], + plugins: [ + require.resolve('babel-plugin-add-module-exports'), + // stage 3 + require.resolve('babel-plugin-transform-async-generator-functions'), + require.resolve('babel-plugin-transform-object-rest-spread'), + + // the class properties proposal was merged with the private fields proposal + // into the "class fields" proposal. Babel doesn't support this combined + // proposal yet, which includes private field, so this transform is + // TECHNICALLY stage 2, but for all intents and purposes it's stage 3 + // + // See https://github.com/babel/proposals/issues/12 for progress + require.resolve('babel-plugin-transform-class-properties'), + ], +}; diff --git a/packages/kbn-babel-preset/node.js b/packages/kbn-babel-preset/node_preset.js similarity index 51% rename from packages/kbn-babel-preset/node.js rename to packages/kbn-babel-preset/node_preset.js index ad56ffd4797809..04d6dd3609e8ad 100644 --- a/packages/kbn-babel-preset/node.js +++ b/packages/kbn-babel-preset/node_preset.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = { presets: [ [ @@ -18,7 +37,7 @@ module.exports = { useBuiltIns: true, }, ], - require('./common'), + require('./common_preset'), ], plugins: [ [ diff --git a/packages/kbn-babel-preset/webpack.js b/packages/kbn-babel-preset/webpack.js deleted file mode 100644 index 071ffc1ba1ed34..00000000000000 --- a/packages/kbn-babel-preset/webpack.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - presets: [ - [ - require.resolve('babel-preset-env'), - { - targets: { - browsers: [ - 'last 2 versions', - '> 5%', - 'Safari 7', // for PhantomJS support - ], - }, - useBuiltIns: true, - }, - ], - require('./common'), - ] -}; diff --git a/packages/kbn-babel-preset/webpack_preset.js b/packages/kbn-babel-preset/webpack_preset.js new file mode 100644 index 00000000000000..511641497c4d53 --- /dev/null +++ b/packages/kbn-babel-preset/webpack_preset.js @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +module.exports = { + presets: [ + [ + require.resolve('babel-preset-env'), + { + targets: { + browsers: [ + 'last 2 versions', + '> 5%', + 'Safari 7', // for PhantomJS support + ], + }, + useBuiltIns: true, + }, + ], + require('./common_preset'), + ] +}; diff --git a/packages/kbn-datemath/src/index.js b/packages/kbn-datemath/src/index.js index d74969c0178bd7..6389fa0470fec7 100644 --- a/packages/kbn-datemath/src/index.js +++ b/packages/kbn-datemath/src/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import moment from 'moment'; const units = ['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms']; diff --git a/packages/kbn-datemath/test/index.js b/packages/kbn-datemath/test/index.js index 4b13c27a2257ba..2f534b095a8d01 100644 --- a/packages/kbn-datemath/test/index.js +++ b/packages/kbn-datemath/test/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import dateMath from '../src/index'; import moment from 'moment'; import sinon from 'sinon'; @@ -355,8 +374,8 @@ describe('dateMath', function() { dateMath.parse('now', { momentInstance: m1 }); expect(m1Spy.called).to.be(true); expect(m2Spy.called).to.be(false); - m1Spy.reset(); - m2Spy.reset(); + m1Spy.resetHistory(); + m2Spy.resetHistory(); dateMath.parse('now', { momentInstance: m2 }); expect(m1Spy.called).to.be(false); expect(m2Spy.called).to.be(true); @@ -371,8 +390,8 @@ describe('dateMath', function() { dateMath.parse('now', { momentInstance: m }); expect(momentSpy.called).to.be(false); expect(cloneSpy.called).to.be(true); - momentSpy.reset(); - cloneSpy.reset(); + momentSpy.resetHistory(); + cloneSpy.resetHistory(); dateMath.parse('now'); expect(momentSpy.called).to.be(true); expect(cloneSpy.called).to.be(false); diff --git a/packages/kbn-dev-utils/.babelrc b/packages/kbn-dev-utils/.babelrc index 36d8928ea14a56..7da72d17791281 100644 --- a/packages/kbn-dev-utils/.babelrc +++ b/packages/kbn-dev-utils/.babelrc @@ -1,3 +1,3 @@ { - "presets": ["@kbn/babel-preset/node"] + "presets": ["@kbn/babel-preset/node_preset"] } diff --git a/packages/kbn-dev-utils/index.d.ts b/packages/kbn-dev-utils/index.d.ts new file mode 100644 index 00000000000000..aca97e4148a8e8 --- /dev/null +++ b/packages/kbn-dev-utils/index.d.ts @@ -0,0 +1,18 @@ +import { Readable } from 'stream'; + +type LogLevel = 'silent' | 'error' | 'warning' | 'info' | 'debug' | 'verbose'; + +export class ToolingLog extends Readable { + public verbose(...args: any[]): void; + public debug(...args: any[]): void; + public info(...args: any[]): void; + public success(...args: any[]): void; + public warning(...args: any[]): void; + public error(errOrMsg: string | Error): void; + public write(...args: any[]): void; + public indent(spaces: number): void; + public getLevel(): LogLevel; + public setLevel(level: LogLevel): void; +} + +export function createToolingLog(level?: LogLevel): ToolingLog; diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json index aa824ced3710b4..8ba55d6a4f5722 100644 --- a/packages/kbn-dev-utils/package.json +++ b/packages/kbn-dev-utils/package.json @@ -1,6 +1,7 @@ { "name": "@kbn/dev-utils", "main": "./target/index.js", + "types": "./index.d.ts", "version": "1.0.0", "license": "Apache-2.0", "private": true, diff --git a/packages/kbn-dev-utils/src/index.js b/packages/kbn-dev-utils/src/index.js index ecd847f13b7a71..56e74e59cef414 100644 --- a/packages/kbn-dev-utils/src/index.js +++ b/packages/kbn-dev-utils/src/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { withProcRunner } from './proc_runner'; export { createToolingLog, pickLevelFromFlags } from './tooling_log'; diff --git a/packages/kbn-dev-utils/src/proc_runner/__tests__/with_proc_runner.js b/packages/kbn-dev-utils/src/proc_runner/__tests__/with_proc_runner.js index 1bedd1bf58650f..f65d76035bb879 100644 --- a/packages/kbn-dev-utils/src/proc_runner/__tests__/with_proc_runner.js +++ b/packages/kbn-dev-utils/src/proc_runner/__tests__/with_proc_runner.js @@ -1,3 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createToolingLog } from '../../tooling_log'; import { withProcRunner } from '../with_proc_runner'; describe('proc runner', () => { @@ -14,7 +34,7 @@ describe('proc runner', () => { } it('passes procs to a function', async () => { - await withProcRunner(async procs => { + await withProcRunner(createToolingLog(), async procs => { await runProc({ procs }); await procs.stop('proc'); }); diff --git a/packages/kbn-dev-utils/src/proc_runner/errors.js b/packages/kbn-dev-utils/src/proc_runner/errors.js index 7c823cb67c3c56..9374e77f49f4e9 100644 --- a/packages/kbn-dev-utils/src/proc_runner/errors.js +++ b/packages/kbn-dev-utils/src/proc_runner/errors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const $isCliError = Symbol('isCliError'); export function createCliError(message) { diff --git a/packages/kbn-dev-utils/src/proc_runner/index.js b/packages/kbn-dev-utils/src/proc_runner/index.js index a539bbc547c453..ad5e7c8ee946e5 100644 --- a/packages/kbn-dev-utils/src/proc_runner/index.js +++ b/packages/kbn-dev-utils/src/proc_runner/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { withProcRunner } from './with_proc_runner'; diff --git a/packages/kbn-dev-utils/src/proc_runner/log.js b/packages/kbn-dev-utils/src/proc_runner/log.js deleted file mode 100644 index 9a296f502ab597..00000000000000 --- a/packages/kbn-dev-utils/src/proc_runner/log.js +++ /dev/null @@ -1,4 +0,0 @@ -import { createToolingLog } from '../tooling_log'; - -export const log = createToolingLog('debug'); -log.pipe(process.stdout); diff --git a/packages/kbn-dev-utils/src/proc_runner/observe_lines.js b/packages/kbn-dev-utils/src/proc_runner/observe_lines.js index a7b02855d20dd9..b214dee46149fd 100644 --- a/packages/kbn-dev-utils/src/proc_runner/observe_lines.js +++ b/packages/kbn-dev-utils/src/proc_runner/observe_lines.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Rx from 'rxjs/Rx'; const SEP = /\r?\n/; diff --git a/packages/kbn-dev-utils/src/proc_runner/observe_readable.js b/packages/kbn-dev-utils/src/proc_runner/observe_readable.js index 0fd8353d82af4e..f41c76ceb00816 100644 --- a/packages/kbn-dev-utils/src/proc_runner/observe_readable.js +++ b/packages/kbn-dev-utils/src/proc_runner/observe_readable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Rx from 'rxjs/Rx'; /** diff --git a/packages/kbn-dev-utils/src/proc_runner/observe_signals.js b/packages/kbn-dev-utils/src/proc_runner/observe_signals.js index 0865131ba29be9..34c6ad7a53c624 100644 --- a/packages/kbn-dev-utils/src/proc_runner/observe_signals.js +++ b/packages/kbn-dev-utils/src/proc_runner/observe_signals.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Rx from 'rxjs/Rx'; /** diff --git a/packages/kbn-dev-utils/src/proc_runner/proc.js b/packages/kbn-dev-utils/src/proc_runner/proc.js index 2e3c0614b6b0de..5a7d6e1b8dbe8e 100644 --- a/packages/kbn-dev-utils/src/proc_runner/proc.js +++ b/packages/kbn-dev-utils/src/proc_runner/proc.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import execa from 'execa'; import { statSync } from 'fs'; @@ -8,7 +27,6 @@ import treeKill from 'tree-kill'; import { promisify } from 'util'; const treeKillAsync = promisify(treeKill); -import { log } from './log'; import { observeLines } from './observe_lines'; import { createCliError } from './errors'; @@ -33,7 +51,7 @@ async function withTimeout(attempt, ms, onTimeout) { } } -export function createProc(name, { cmd, args, cwd, env, stdin }) { +export function createProc(name, { cmd, args, cwd, env, stdin, log }) { log.info('[%s] > %s', name, cmd, args.join(' ')); // spawn fails with ENOENT when either the @@ -78,7 +96,7 @@ export function createProc(name, { cmd, args, cwd, env, stdin }) { .map(code => { // JVM exits with 143 on SIGTERM and 130 on SIGINT, dont' treat then as errors if (code > 0 && !(code === 143 || code === 130)) { - throw createCliError(`[${name}] exitted with code ${code}`); + throw createCliError(`[${name}] exited with code ${code}`); } return code; @@ -92,11 +110,15 @@ export function createProc(name, { cmd, args, cwd, env, stdin }) { return Rx.Observable.race(exit$, error$); }).share(); - outcomePromise = Rx.Observable.merge( + _outcomePromise = Rx.Observable.merge( this.lines$.ignoreElements(), this.outcome$ ).toPromise(); + getOutcomePromise() { + return this._outcomePromise; + } + async stop(signal) { await withTimeout( async () => { @@ -114,7 +136,7 @@ export function createProc(name, { cmd, args, cwd, env, stdin }) { await withTimeout( async () => { try { - await this.outcomePromise; + await this.getOutcomePromise(); } catch (error) { // ignore } diff --git a/packages/kbn-dev-utils/src/proc_runner/proc_runner.js b/packages/kbn-dev-utils/src/proc_runner/proc_runner.js index c6d1fb11e558d4..e324424311ff73 100644 --- a/packages/kbn-dev-utils/src/proc_runner/proc_runner.js +++ b/packages/kbn-dev-utils/src/proc_runner/proc_runner.js @@ -1,6 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import moment from 'moment'; -import { log } from './log'; import { createCliError } from './errors'; import { createProc } from './proc'; import { observeSignals } from './observe_signals'; @@ -15,9 +33,12 @@ const noop = () => {}; * @class ProcRunner */ export class ProcRunner { - constructor() { + constructor(options) { + const { log } = options; + this._closing = false; this._procs = []; + this._log = log; this._signalSubscription = observeSignals(process).subscribe({ next: async signal => { await this.teardown(signal); @@ -75,7 +96,7 @@ export class ProcRunner { .catch(err => { if (err.name !== 'EmptyError') { throw createCliError( - `[${name}] exitted without matching pattern: ${wait}` + `[${name}] exited without matching pattern: ${wait}` ); } else { throw err; @@ -86,7 +107,7 @@ export class ProcRunner { // wait for process to complete if (wait === true) { - await proc.outcomePromise; + await proc.getOutcomePromise(); } } finally { // while the procRunner closes promises will resolve/reject because @@ -109,7 +130,7 @@ export class ProcRunner { if (proc) { await proc.stop(signal); } else { - log.warning('[%s] already stopped', name); + this._log.warning('[%s] already stopped', name); } } @@ -118,7 +139,7 @@ export class ProcRunner { * @return {Promise} */ async waitForAllToStop() { - await Promise.all(this._procs.map(proc => proc.closedPromise)); + await Promise.all(this._procs.map(proc => proc.getOutcomePromise())); } /** @@ -136,7 +157,7 @@ export class ProcRunner { this._signalSubscription = null; if (!signal && this._procs.length > 0) { - log.warning( + this._log.warning( '%d processes left running, stop them with procs.stop(name):', this._procs.length, this._procs.map(proc => proc.name) @@ -153,7 +174,10 @@ export class ProcRunner { _createProc(name, options) { const startMs = Date.now(); - const proc = createProc(name, options); + const proc = createProc(name, { + ...options, + log: this._log, + }); this._procs.push(proc); const remove = () => { @@ -164,8 +188,8 @@ export class ProcRunner { proc.outcome$.subscribe({ next: code => { const duration = moment.duration(Date.now() - startMs); - log.info( - '[%s] exitted with %s after %s', + this._log.info( + '[%s] exited with %s after %s', name, code, duration.humanize() @@ -176,7 +200,7 @@ export class ProcRunner { }, error: error => { if (this._closing) { - log.error(error); + this._log.error(error); } remove(); }, diff --git a/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.js b/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.js index 15c4fa61d4c4dd..21994d8ec8360e 100644 --- a/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.js +++ b/packages/kbn-dev-utils/src/proc_runner/with_proc_runner.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { ProcRunner } from './proc_runner'; /** @@ -5,11 +24,12 @@ import { ProcRunner } from './proc_runner'; * the async function finishes the ProcRunner is torn-down * automatically * + * @param {ToolingLog} log * @param {async Function} fn * @return {Promise} */ -export async function withProcRunner(fn) { - const procs = new ProcRunner(); +export async function withProcRunner(log, fn) { + const procs = new ProcRunner({ log }); try { await fn(procs); } finally { diff --git a/packages/kbn-dev-utils/src/streams/concat_stream.js b/packages/kbn-dev-utils/src/streams/concat_stream.js index 4697f4062a8c01..89b0dff3b3d148 100644 --- a/packages/kbn-dev-utils/src/streams/concat_stream.js +++ b/packages/kbn-dev-utils/src/streams/concat_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { createReduceStream } from './reduce_stream'; /** diff --git a/packages/kbn-dev-utils/src/streams/index.js b/packages/kbn-dev-utils/src/streams/index.js index 6e59a39f1688d1..18fda5995090f5 100644 --- a/packages/kbn-dev-utils/src/streams/index.js +++ b/packages/kbn-dev-utils/src/streams/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { createConcatStream } from './concat_stream'; export { createPromiseFromStreams } from './promise_from_streams'; diff --git a/packages/kbn-dev-utils/src/streams/promise_from_streams.js b/packages/kbn-dev-utils/src/streams/promise_from_streams.js index 856c51de6201de..c6e76b7a99411e 100644 --- a/packages/kbn-dev-utils/src/streams/promise_from_streams.js +++ b/packages/kbn-dev-utils/src/streams/promise_from_streams.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Take an array of streams, pipe the output * from each one into the next, listening for diff --git a/packages/kbn-dev-utils/src/streams/reduce_stream.js b/packages/kbn-dev-utils/src/streams/reduce_stream.js index d09721fb5f67f4..d66b0124d1dab9 100644 --- a/packages/kbn-dev-utils/src/streams/reduce_stream.js +++ b/packages/kbn-dev-utils/src/streams/reduce_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Transform } from 'stream'; /** diff --git a/packages/kbn-dev-utils/src/tooling_log/__tests__/log.js b/packages/kbn-dev-utils/src/tooling_log/__tests__/log.js index 798ee7e9553e69..a07b5162d48246 100644 --- a/packages/kbn-dev-utils/src/tooling_log/__tests__/log.js +++ b/packages/kbn-dev-utils/src/tooling_log/__tests__/log.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import Chance from 'chance'; diff --git a/packages/kbn-dev-utils/src/tooling_log/__tests__/log_levels.js b/packages/kbn-dev-utils/src/tooling_log/__tests__/log_levels.js index 78778cd4a9deda..fafd0b28aa9df6 100644 --- a/packages/kbn-dev-utils/src/tooling_log/__tests__/log_levels.js +++ b/packages/kbn-dev-utils/src/tooling_log/__tests__/log_levels.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import Chance from 'chance'; import { parseLogLevel } from '../log_levels'; diff --git a/packages/kbn-dev-utils/src/tooling_log/index.js b/packages/kbn-dev-utils/src/tooling_log/index.js index bab8ff1bc89103..9d1f820e39a06d 100644 --- a/packages/kbn-dev-utils/src/tooling_log/index.js +++ b/packages/kbn-dev-utils/src/tooling_log/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { createToolingLog } from './tooling_log'; export { pickLevelFromFlags } from './log_levels'; diff --git a/packages/kbn-dev-utils/src/tooling_log/log_levels.js b/packages/kbn-dev-utils/src/tooling_log/log_levels.js index 9ede25a7be353b..90ab8d732b09bc 100644 --- a/packages/kbn-dev-utils/src/tooling_log/log_levels.js +++ b/packages/kbn-dev-utils/src/tooling_log/log_levels.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const LEVELS = ['silent', 'error', 'warning', 'info', 'debug', 'verbose']; export function pickLevelFromFlags(flags) { diff --git a/packages/kbn-dev-utils/src/tooling_log/tooling_log.js b/packages/kbn-dev-utils/src/tooling_log/tooling_log.js index 537f8dbd9bdb12..567cf068de3592 100644 --- a/packages/kbn-dev-utils/src/tooling_log/tooling_log.js +++ b/packages/kbn-dev-utils/src/tooling_log/tooling_log.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { format } from 'util'; import { PassThrough } from 'stream'; diff --git a/packages/kbn-dev-utils/tsconfig.json b/packages/kbn-dev-utils/tsconfig.json new file mode 100644 index 00000000000000..3604f1004cf6c4 --- /dev/null +++ b/packages/kbn-dev-utils/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "include": [ + "index.d.ts" + ], +} diff --git a/packages/kbn-es/src/cli.js b/packages/kbn-es/src/cli.js index 9b9664aa997bfd..e9acd441aef164 100644 --- a/packages/kbn-es/src/cli.js +++ b/packages/kbn-es/src/cli.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const chalk = require('chalk'); const getopts = require('getopts'); const dedent = require('dedent'); diff --git a/packages/kbn-es/src/cli_commands/archive.js b/packages/kbn-es/src/cli_commands/archive.js index 9e53dc8a51ac26..c269b1e7bae846 100644 --- a/packages/kbn-es/src/cli_commands/archive.js +++ b/packages/kbn-es/src/cli_commands/archive.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const dedent = require('dedent'); const getopts = require('getopts'); const { Cluster } = require('../cluster'); diff --git a/packages/kbn-es/src/cli_commands/index.js b/packages/kbn-es/src/cli_commands/index.js index 254430a7de4456..2c9c3bd849f17a 100644 --- a/packages/kbn-es/src/cli_commands/index.js +++ b/packages/kbn-es/src/cli_commands/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + exports.snapshot = require('./snapshot'); exports.source = require('./source'); exports.archive = require('./archive'); diff --git a/packages/kbn-es/src/cli_commands/snapshot.js b/packages/kbn-es/src/cli_commands/snapshot.js index 2a668e31f738fc..a90ac9c6e10a35 100644 --- a/packages/kbn-es/src/cli_commands/snapshot.js +++ b/packages/kbn-es/src/cli_commands/snapshot.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const dedent = require('dedent'); const getopts = require('getopts'); const { Cluster } = require('../cluster'); diff --git a/packages/kbn-es/src/cli_commands/source.js b/packages/kbn-es/src/cli_commands/source.js index 7cb5934274bbd5..77940a1f9e6ba7 100644 --- a/packages/kbn-es/src/cli_commands/source.js +++ b/packages/kbn-es/src/cli_commands/source.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const dedent = require('dedent'); const getopts = require('getopts'); const { Cluster } = require('../cluster'); diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js index 4ace6a341264b9..f9389ed1b26624 100644 --- a/packages/kbn-es/src/cluster.js +++ b/packages/kbn-es/src/cluster.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const execa = require('execa'); const chalk = require('chalk'); const { installSnapshot, installSource, installArchive } = require('./install'); diff --git a/packages/kbn-es/src/errors.js b/packages/kbn-es/src/errors.js index b7238e1a01b5cb..099b5214bcbdb3 100644 --- a/packages/kbn-es/src/errors.js +++ b/packages/kbn-es/src/errors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + exports.createCliError = function(message) { const error = new Error(message); error.isCliError = true; diff --git a/packages/kbn-es/src/index.js b/packages/kbn-es/src/index.js index 356d24c14d0a65..0f3adda0e849ec 100644 --- a/packages/kbn-es/src/index.js +++ b/packages/kbn-es/src/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + exports.run = require('./cli').run; exports.Cluster = require('./cluster').Cluster; diff --git a/packages/kbn-es/src/install/archive.js b/packages/kbn-es/src/install/archive.js index fe7b68d6eb22cc..8b1213c707efa0 100644 --- a/packages/kbn-es/src/install/archive.js +++ b/packages/kbn-es/src/install/archive.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); diff --git a/packages/kbn-es/src/install/index.js b/packages/kbn-es/src/install/index.js index baf2a4facf04a2..69de1004e4e722 100644 --- a/packages/kbn-es/src/install/index.js +++ b/packages/kbn-es/src/install/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + exports.installArchive = require('./archive').installArchive; exports.installSnapshot = require('./snapshot').installSnapshot; exports.installSource = require('./source').installSource; diff --git a/packages/kbn-es/src/install/snapshot.js b/packages/kbn-es/src/install/snapshot.js index e3dad86f97cdd3..131a1d506ef7f3 100644 --- a/packages/kbn-es/src/install/snapshot.js +++ b/packages/kbn-es/src/install/snapshot.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const fetch = require('node-fetch'); const fs = require('fs'); const mkdirp = require('mkdirp'); @@ -97,9 +116,9 @@ function downloadFile(url, dest, log) { } function getFilename(license, version) { - if (license === 'oss') { - return `elasticsearch-oss/elasticsearch-oss-${version}-SNAPSHOT.tar.gz`; - } + const basename = `elasticsearch${ + license === 'oss' ? '-oss-' : '-' + }${version}`; - return `elasticsearch-${version}-SNAPSHOT.tar.gz`; + return `${basename}-SNAPSHOT.tar.gz`; } diff --git a/packages/kbn-es/src/install/source.js b/packages/kbn-es/src/install/source.js index d9528bb1ca12a1..1fde1172734faf 100644 --- a/packages/kbn-es/src/install/source.js +++ b/packages/kbn-es/src/install/source.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const execa = require('execa'); const path = require('path'); const fs = require('fs'); diff --git a/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js b/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js index f1dc0e736a0bf6..d07d5e24a641f1 100644 --- a/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js +++ b/packages/kbn-es/src/integration_tests/__fixtures__/es_bin.js @@ -1,5 +1,24 @@ #!/usr/bin/env node +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { exitCode, start } = JSON.parse(process.argv[2]); if (start) { diff --git a/packages/kbn-es/src/integration_tests/cluster.test.js b/packages/kbn-es/src/integration_tests/cluster.test.js index 42ccae8ad0f454..d381019fa034aa 100644 --- a/packages/kbn-es/src/integration_tests/cluster.test.js +++ b/packages/kbn-es/src/integration_tests/cluster.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { createToolingLog } = require('@kbn/dev-utils'); const execa = require('execa'); const { Cluster } = require('../cluster'); diff --git a/packages/kbn-es/src/paths.js b/packages/kbn-es/src/paths.js index 6e0c54ba99cac8..4c911bc5e6bf1b 100644 --- a/packages/kbn-es/src/paths.js +++ b/packages/kbn-es/src/paths.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const os = require('os'); const path = require('path'); diff --git a/packages/kbn-es/src/utils/cache.js b/packages/kbn-es/src/utils/cache.js index 7ba413cf8a4e3f..01f4b9f374c925 100644 --- a/packages/kbn-es/src/utils/cache.js +++ b/packages/kbn-es/src/utils/cache.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const fs = require('fs'); const mkdirp = require('mkdirp'); const path = require('path'); diff --git a/packages/kbn-es/src/utils/extract_config_files.js b/packages/kbn-es/src/utils/extract_config_files.js index cfa0d153ae2692..38eab6952c3d5f 100644 --- a/packages/kbn-es/src/utils/extract_config_files.js +++ b/packages/kbn-es/src/utils/extract_config_files.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const path = require('path'); const fs = require('fs'); const mkdirp = require('mkdirp'); diff --git a/packages/kbn-es/src/utils/extract_config_files.test.js b/packages/kbn-es/src/utils/extract_config_files.test.js index 9369b700d5b71d..5f1cdda96045ed 100644 --- a/packages/kbn-es/src/utils/extract_config_files.test.js +++ b/packages/kbn-es/src/utils/extract_config_files.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { extractConfigFiles } = require('./extract_config_files'); const mockFs = require('mock-fs'); const fs = require('fs'); diff --git a/packages/kbn-es/src/utils/find_most_recently_changed.js b/packages/kbn-es/src/utils/find_most_recently_changed.js index 57371ef22b96f8..0fcd87978c3579 100644 --- a/packages/kbn-es/src/utils/find_most_recently_changed.js +++ b/packages/kbn-es/src/utils/find_most_recently_changed.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const path = require('path'); const fs = require('fs'); const glob = require('glob'); diff --git a/packages/kbn-es/src/utils/find_most_recently_changed.test.js b/packages/kbn-es/src/utils/find_most_recently_changed.test.js index 55768adf988f69..6ceb9a9f08c4ee 100644 --- a/packages/kbn-es/src/utils/find_most_recently_changed.test.js +++ b/packages/kbn-es/src/utils/find_most_recently_changed.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const mockFs = require('mock-fs'); const { findMostRecentlyChanged } = require('./find_most_recently_changed'); diff --git a/packages/kbn-es/src/utils/index.js b/packages/kbn-es/src/utils/index.js index c1486b9e79a0dd..cc06bbbbfe024a 100644 --- a/packages/kbn-es/src/utils/index.js +++ b/packages/kbn-es/src/utils/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + exports.cache = require('./cache'); exports.log = require('./log').log; exports.parseEsLog = require('./parse_es_log').parseEsLog; diff --git a/packages/kbn-es/src/utils/log.js b/packages/kbn-es/src/utils/log.js index d037c8217a7be8..bb2e96b8c089c2 100644 --- a/packages/kbn-es/src/utils/log.js +++ b/packages/kbn-es/src/utils/log.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { createToolingLog } = require('@kbn/dev-utils'); const log = createToolingLog('verbose'); diff --git a/packages/kbn-es/src/utils/parse_es_log.js b/packages/kbn-es/src/utils/parse_es_log.js index 6a3b7089c60c1b..8cbec104a2a34b 100644 --- a/packages/kbn-es/src/utils/parse_es_log.js +++ b/packages/kbn-es/src/utils/parse_es_log.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const chalk = require('chalk'); /** diff --git a/packages/kbn-es/src/utils/parse_es_log.test.js b/packages/kbn-es/src/utils/parse_es_log.test.js index 772fdd19966bd6..9c21c6ebf15856 100644 --- a/packages/kbn-es/src/utils/parse_es_log.test.js +++ b/packages/kbn-es/src/utils/parse_es_log.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const dedent = require('dedent'); const { parseEsLog } = require('./parse_es_log'); diff --git a/packages/kbn-es/src/utils/tarball.js b/packages/kbn-es/src/utils/tarball.js index bd201a9cbca11a..f4d396343c8173 100644 --- a/packages/kbn-es/src/utils/tarball.js +++ b/packages/kbn-es/src/utils/tarball.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const fs = require('fs'); const zlib = require('zlib'); const path = require('path'); diff --git a/packages/kbn-eslint-import-resolver-kibana/import_resolver_kibana.js b/packages/kbn-eslint-import-resolver-kibana/import_resolver_kibana.js index 26f1cbc683e51f..5c409ade260b13 100755 --- a/packages/kbn-eslint-import-resolver-kibana/import_resolver_kibana.js +++ b/packages/kbn-eslint-import-resolver-kibana/import_resolver_kibana.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { join, dirname, extname } = require('path'); const webpackResolver = require('eslint-import-resolver-webpack'); @@ -33,8 +52,36 @@ function initContext(file, config) { return context; } +function tryNodeResolver(importRequest, file, config) { + return nodeResolver.resolve( + importRequest, + file, + // we use Object.assign so that this file is compatible with slightly older + // versions of node.js used by IDEs (eg. resolvers are run in the Electron + // process in Atom) + Object.assign({}, config, { + extensions: ['.js', '.json', '.ts', '.tsx'], + isFile, + }) + ); +} + exports.resolve = function resolveKibanaPath(importRequest, file, config) { config = config || {}; + + if (config.forceNode) { + return tryNodeResolver(importRequest, file, config); + } + + // these modules are simulated by webpack, so there is no + // path to resolve to and no reason to do any more work + if (importRequest.startsWith('uiExports/')) { + return { + found: true, + path: null, + }; + } + const { webpackConfig, aliasEntries } = initContext(file, config); let isPathRequest = getIsPathRequest(importRequest); @@ -69,14 +116,7 @@ exports.resolve = function resolveKibanaPath(importRequest, file, config) { // to the node_modules directory by the node resolver, but we want // them to resolve to the actual shim if (isPathRequest || !isProbablyWebpackShim(importRequest, file)) { - const nodeResult = nodeResolver.resolve( - importRequest, - file, - Object.assign({}, config, { - isFile, - }) - ); - + const nodeResult = tryNodeResolver(importRequest, file, config); if (nodeResult && nodeResult.found) { return nodeResult; } diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/debug.js b/packages/kbn-eslint-import-resolver-kibana/lib/debug.js index 83cbdbc6578361..40894a97c8fdad 100755 --- a/packages/kbn-eslint-import-resolver-kibana/lib/debug.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/debug.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + exports.debug = require('debug')('eslint-plugin-import:resolver:kibana'); diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_is_path_request.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_is_path_request.js index a2f82bc6cf0131..e26660f76a5502 100644 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_is_path_request.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_is_path_request.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // "path" imports point to a specific location and don't require // module directory resolution. This RegExp should capture import // statements that: diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js index bc28b0c05857db..f7f773c27c477c 100755 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_kibana_path.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { resolve } = require('path'); const { debug } = require('./debug'); diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_path_type.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_path_type.js index e70ad97fce388c..5ffb678dcf0caa 100644 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_path_type.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_path_type.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { statSync } = require('fs'); const LRU = require('lru-cache'); diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_plugins.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_plugins.js index 4f4b48b0cc0d68..9a122c28b17295 100755 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_plugins.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_plugins.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { dirname, resolve } = require('path'); const glob = require('glob-all'); diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_project_root.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_project_root.js index d1b2ad9511f39e..45b99b4961ee7b 100755 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_project_root.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_project_root.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { dirname, resolve, parse } = require('path'); const { accessSync, readFileSync } = require('fs'); diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js b/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js index 4ae951713c2935..64bb3a08940aff 100755 --- a/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/get_webpack_config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { resolve } = require('path'); const { debug } = require('./debug'); @@ -33,7 +52,7 @@ exports.getWebpackConfig = function(kibanaPath, projectRoot, config) { return { context: kibanaPath, resolve: { - extensions: ['.js', '.json'], + extensions: ['.js', '.json', '.ts', '.tsx'], mainFields: ['browser', 'main'], modules: [ 'webpackShims', diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/index.js b/packages/kbn-eslint-import-resolver-kibana/lib/index.js index c2d890249e917b..465ba2f740ac34 100644 --- a/packages/kbn-eslint-import-resolver-kibana/lib/index.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = Object.assign( {}, require('./get_kibana_path'), diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/is_probably_webpack_shim.js b/packages/kbn-eslint-import-resolver-kibana/lib/is_probably_webpack_shim.js index 3e36c57a7d91b9..8734140598d6cb 100644 --- a/packages/kbn-eslint-import-resolver-kibana/lib/is_probably_webpack_shim.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/is_probably_webpack_shim.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { readdirSync } = require('fs'); const { join, dirname } = require('path'); diff --git a/packages/kbn-eslint-import-resolver-kibana/lib/resolve_webpack_alias.js b/packages/kbn-eslint-import-resolver-kibana/lib/resolve_webpack_alias.js index c17cc528e11413..d4b483f9e44480 100644 --- a/packages/kbn-eslint-import-resolver-kibana/lib/resolve_webpack_alias.js +++ b/packages/kbn-eslint-import-resolver-kibana/lib/resolve_webpack_alias.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Attempt to apply basic webpack alias transfomations so we can * avoid triggering the webpack resolver for many imports diff --git a/packages/kbn-eslint-plugin-license-header/index.js b/packages/kbn-eslint-plugin-license-header/index.js index 1d47df2fb3ede3..093487c8691caf 100644 --- a/packages/kbn-eslint-plugin-license-header/index.js +++ b/packages/kbn-eslint-plugin-license-header/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = { rules: { 'require-license-header': require('./rules/require_license_header'), diff --git a/packages/kbn-eslint-plugin-license-header/lib.js b/packages/kbn-eslint-plugin-license-header/lib.js index 5c24ab4470bf6a..5d632b7c328c37 100644 --- a/packages/kbn-eslint-plugin-license-header/lib.js +++ b/packages/kbn-eslint-plugin-license-header/lib.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + exports.assert = function assert(truth, message) { if (truth) { return; diff --git a/packages/kbn-eslint-plugin-license-header/rules/__tests__/remove_outdated_license_header.js b/packages/kbn-eslint-plugin-license-header/rules/__tests__/remove_outdated_license_header.js index da075842172063..f230f2bbe2fc42 100644 --- a/packages/kbn-eslint-plugin-license-header/rules/__tests__/remove_outdated_license_header.js +++ b/packages/kbn-eslint-plugin-license-header/rules/__tests__/remove_outdated_license_header.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { RuleTester } = require('eslint'); const rule = require('../remove_outdated_license_header'); const dedent = require('dedent'); diff --git a/packages/kbn-eslint-plugin-license-header/rules/__tests__/require_license_header.js b/packages/kbn-eslint-plugin-license-header/rules/__tests__/require_license_header.js index e5ecddd5f223d6..86c7ea32445419 100644 --- a/packages/kbn-eslint-plugin-license-header/rules/__tests__/require_license_header.js +++ b/packages/kbn-eslint-plugin-license-header/rules/__tests__/require_license_header.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { RuleTester } = require('eslint'); const rule = require('../require_license_header'); const dedent = require('dedent'); diff --git a/packages/kbn-eslint-plugin-license-header/rules/remove_outdated_license_header.js b/packages/kbn-eslint-plugin-license-header/rules/remove_outdated_license_header.js index 8d6ac5c732a3a8..9993133f729b18 100644 --- a/packages/kbn-eslint-plugin-license-header/rules/remove_outdated_license_header.js +++ b/packages/kbn-eslint-plugin-license-header/rules/remove_outdated_license_header.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const babelEslint = require('babel-eslint'); const { assert, normalizeWhitespace, init } = require('../lib'); diff --git a/packages/kbn-eslint-plugin-license-header/rules/require_license_header.js b/packages/kbn-eslint-plugin-license-header/rules/require_license_header.js index 27c4759378f273..6aa1a6223b628b 100644 --- a/packages/kbn-eslint-plugin-license-header/rules/require_license_header.js +++ b/packages/kbn-eslint-plugin-license-header/rules/require_license_header.js @@ -1,7 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const babelEslint = require('babel-eslint'); const { assert, normalizeWhitespace, init } = require('../lib'); +function isHashbang(text) { + return text.trim().startsWith('#!') && !text.trim().includes('\n'); +} + module.exports = { meta: { fixable: 'code', @@ -52,6 +75,10 @@ module.exports = { end: { line: 1, column: sourceCode.lines[0].length - 1 } }, fix(fixer) { + if (isHashbang(sourceCode.lines[0])) { + return undefined; + } + return fixer.replaceTextRange([0, 0], license.source + '\n\n'); } }); @@ -60,7 +87,7 @@ module.exports = { // ensure there is nothing before the comment const sourceBeforeNode = sourceCode.getText().slice(0, sourceCode.getIndexFromLoc(comment.loc.start)); - if (sourceBeforeNode.length) { + if (sourceBeforeNode.length && !isHashbang(sourceBeforeNode)) { context.report({ node: comment, message: 'License header must be at the very beginning of the file', diff --git a/packages/kbn-plugin-generator/index.js b/packages/kbn-plugin-generator/index.js index 9946cd306841c6..0ee17ee72708cb 100644 --- a/packages/kbn-plugin-generator/index.js +++ b/packages/kbn-plugin-generator/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { resolve } = require('path'); const dedent = require('dedent'); diff --git a/packages/kbn-plugin-generator/sao_template/sao.js b/packages/kbn-plugin-generator/sao_template/sao.js index ac731c289b4e1d..1891e7e7465382 100755 --- a/packages/kbn-plugin-generator/sao_template/sao.js +++ b/packages/kbn-plugin-generator/sao_template/sao.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { resolve, relative, dirname } = require('path'); const kebabCase = require('lodash.kebabcase'); diff --git a/packages/kbn-plugin-generator/sao_template/sao.test.js b/packages/kbn-plugin-generator/sao_template/sao.test.js index 4e836a9ca71a5f..aa1bd850b9d8b7 100755 --- a/packages/kbn-plugin-generator/sao_template/sao.test.js +++ b/packages/kbn-plugin-generator/sao_template/sao.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const sao = require('sao'); const templatePkg = require('../package.json'); diff --git a/packages/kbn-plugin-helpers/README.md b/packages/kbn-plugin-helpers/README.md index 47353c90e6e9d7..b1fe525a9c116f 100644 --- a/packages/kbn-plugin-helpers/README.md +++ b/packages/kbn-plugin-helpers/README.md @@ -72,3 +72,20 @@ Setting | Description `skipInstallDependencies` | Don't install dependencies defined in package.json into build output `buildVersion` | Version for the build output `kibanaVersion` | Kibana version for the build output (added to package.json) + +## TypeScript support + +Plugin code can be written in [TypeScript](http://www.typescriptlang.org/) if desired. To enable TypeScript support create a `tsconfig.json` file at the root of your plugin that looks something like this: + +```js +{ + // extend Kibana's tsconfig, or use your own settings + "extends": "../../kibana/tsconfig.json", + + // tell the TypeScript compiler where to find your source files + "include": [ + "server/**/*", + "public/**/*" + ] +} +``` diff --git a/packages/kbn-plugin-helpers/bin/plugin-helpers.js b/packages/kbn-plugin-helpers/bin/plugin-helpers.js index 7ca772e91172be..3ae756b9f13123 100755 --- a/packages/kbn-plugin-helpers/bin/plugin-helpers.js +++ b/packages/kbn-plugin-helpers/bin/plugin-helpers.js @@ -1,5 +1,24 @@ #!/usr/bin/env node +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const nodeMajorVersion = parseFloat( process.version.replace(/^v(\d+)\..+/, '$1') ); diff --git a/packages/kbn-plugin-helpers/cli.js b/packages/kbn-plugin-helpers/cli.js index c9dc7d8c1670dd..70b2f0a34ea4ec 100644 --- a/packages/kbn-plugin-helpers/cli.js +++ b/packages/kbn-plugin-helpers/cli.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const program = require('commander'); const pkg = require('./package.json'); diff --git a/packages/kbn-plugin-helpers/lib/commander_action.js b/packages/kbn-plugin-helpers/lib/commander_action.js index ee3962946d166b..6ea700489324b6 100644 --- a/packages/kbn-plugin-helpers/lib/commander_action.js +++ b/packages/kbn-plugin-helpers/lib/commander_action.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const run = require('./run'); module.exports = function createCommanderAction( diff --git a/packages/kbn-plugin-helpers/lib/commander_action.test.js b/packages/kbn-plugin-helpers/lib/commander_action.test.js index 85e400fa1f8eba..40ac6755f02e54 100644 --- a/packages/kbn-plugin-helpers/lib/commander_action.test.js +++ b/packages/kbn-plugin-helpers/lib/commander_action.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /*eslint-env jest*/ const createCommanderAction = require('./commander_action'); diff --git a/packages/kbn-plugin-helpers/lib/config_file.js b/packages/kbn-plugin-helpers/lib/config_file.js index c8fb728981aa35..d82aef5064dbd4 100644 --- a/packages/kbn-plugin-helpers/lib/config_file.js +++ b/packages/kbn-plugin-helpers/lib/config_file.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const resolve = require('path').resolve; const readFileSync = require('fs').readFileSync; diff --git a/packages/kbn-plugin-helpers/lib/docs.js b/packages/kbn-plugin-helpers/lib/docs.js index ddb13e70f4b17b..5de02204911276 100644 --- a/packages/kbn-plugin-helpers/lib/docs.js +++ b/packages/kbn-plugin-helpers/lib/docs.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const resolve = require('path').resolve; const readFileSync = require('fs').readFileSync; diff --git a/packages/kbn-plugin-helpers/lib/enable_collecting_unknown_options.js b/packages/kbn-plugin-helpers/lib/enable_collecting_unknown_options.js index e168c3df499928..8b855a8b8769d2 100644 --- a/packages/kbn-plugin-helpers/lib/enable_collecting_unknown_options.js +++ b/packages/kbn-plugin-helpers/lib/enable_collecting_unknown_options.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = function enableCollectingUnknownOptions(command) { const origParse = command.parseOptions; command.allowUnknownOption(); diff --git a/packages/kbn-plugin-helpers/lib/index.js b/packages/kbn-plugin-helpers/lib/index.js index 3ab7d6334c96fd..836d9de7849dc4 100644 --- a/packages/kbn-plugin-helpers/lib/index.js +++ b/packages/kbn-plugin-helpers/lib/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const run = require('./run'); const utils = require('./utils'); diff --git a/packages/kbn-plugin-helpers/lib/plugin_config.js b/packages/kbn-plugin-helpers/lib/plugin_config.js index 9d7a993bb305c5..dbf22097458465 100644 --- a/packages/kbn-plugin-helpers/lib/plugin_config.js +++ b/packages/kbn-plugin-helpers/lib/plugin_config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const resolve = require('path').resolve; const readFileSync = require('fs').readFileSync; const configFile = require('./config_file'); @@ -10,6 +29,7 @@ module.exports = function(root) { const buildSourcePatterns = [ 'yarn.lock', + 'tsconfig.json', 'package.json', 'index.js', '{lib,public,server,webpackShims,translations}/**/*', diff --git a/packages/kbn-plugin-helpers/lib/run.js b/packages/kbn-plugin-helpers/lib/run.js index cdc02f8df76b4a..119b64f71e2f95 100644 --- a/packages/kbn-plugin-helpers/lib/run.js +++ b/packages/kbn-plugin-helpers/lib/run.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const pluginConfig = require('./plugin_config'); const tasks = require('./tasks'); diff --git a/packages/kbn-plugin-helpers/lib/run.test.js b/packages/kbn-plugin-helpers/lib/run.test.js index f009bcba6bdc02..4c87399319b3bb 100644 --- a/packages/kbn-plugin-helpers/lib/run.test.js +++ b/packages/kbn-plugin-helpers/lib/run.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /*eslint-env jest*/ jest.mock('./plugin_config', () => () => ({ id: 'testPlugin' })); diff --git a/packages/kbn-plugin-helpers/lib/tasks.js b/packages/kbn-plugin-helpers/lib/tasks.js index 756cc4303ec216..608a1617ffdb2a 100644 --- a/packages/kbn-plugin-helpers/lib/tasks.js +++ b/packages/kbn-plugin-helpers/lib/tasks.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const buildTask = require('../tasks/build'); const startTask = require('../tasks/start'); const testAllTask = require('../tasks/test/all'); diff --git a/packages/kbn-plugin-helpers/lib/utils.js b/packages/kbn-plugin-helpers/lib/utils.js index ce23f5b2e0a118..eb36a5b05a014c 100644 --- a/packages/kbn-plugin-helpers/lib/utils.js +++ b/packages/kbn-plugin-helpers/lib/utils.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const resolve = require('path').resolve; const pluginConfig = require('./plugin_config'); @@ -7,7 +26,7 @@ function babelRegister() { try { // add support for moved babel-register source: https://github.com/elastic/kibana/pull/13973 - require(resolve(plugin.kibanaRoot, 'src/babel-register')); + require(resolve(plugin.kibanaRoot, 'src/setup_node_env/babel_register')); } catch (error) { if (error.code === 'MODULE_NOT_FOUND') { require(resolve(plugin.kibanaRoot, 'src/optimize/babel/register')); diff --git a/packages/kbn-plugin-helpers/lib/win_cmd.js b/packages/kbn-plugin-helpers/lib/win_cmd.js index 1d19faa0c12388..0bc672bed67c6b 100644 --- a/packages/kbn-plugin-helpers/lib/win_cmd.js +++ b/packages/kbn-plugin-helpers/lib/win_cmd.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const platform = require('os').platform(); module.exports = function winCmd(cmd) { diff --git a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/build_action_test_plugin/index.js b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/build_action_test_plugin/index.js index cddbaefbbf300b..c2d2ade5687615 100644 --- a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/build_action_test_plugin/index.js +++ b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/build_action_test_plugin/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = kibana => new kibana.Plugin({ uiExports: { diff --git a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/build_action_test_plugin/public/hack.js b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/build_action_test_plugin/public/hack.js index 04ce9f94f87ee5..dbeba25f9dfec6 100644 --- a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/build_action_test_plugin/public/hack.js +++ b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/build_action_test_plugin/public/hack.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + console.log('this is my hack'); diff --git a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_build_test_plugin/index.js b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_build_test_plugin/index.js index cddbaefbbf300b..c2d2ade5687615 100644 --- a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_build_test_plugin/index.js +++ b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_build_test_plugin/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = kibana => new kibana.Plugin({ uiExports: { diff --git a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_build_test_plugin/public/hack.js b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_build_test_plugin/public/hack.js index 04ce9f94f87ee5..dbeba25f9dfec6 100644 --- a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_build_test_plugin/public/hack.js +++ b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_build_test_plugin/public/hack.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + console.log('this is my hack'); diff --git a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_package_test_plugin/index.js b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_package_test_plugin/index.js index cddbaefbbf300b..c2d2ade5687615 100644 --- a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_package_test_plugin/index.js +++ b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_package_test_plugin/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = kibana => new kibana.Plugin({ uiExports: { diff --git a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_package_test_plugin/public/hack.js b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_package_test_plugin/public/hack.js index 04ce9f94f87ee5..dbeba25f9dfec6 100644 --- a/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_package_test_plugin/public/hack.js +++ b/packages/kbn-plugin-helpers/tasks/build/__fixtures__/create_package_test_plugin/public/hack.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + console.log('this is my hack'); diff --git a/packages/kbn-plugin-helpers/tasks/build/build_action.js b/packages/kbn-plugin-helpers/tasks/build/build_action.js index 18e6900e9664f0..810e4eea4f7f8a 100644 --- a/packages/kbn-plugin-helpers/tasks/build/build_action.js +++ b/packages/kbn-plugin-helpers/tasks/build/build_action.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const join = require('path').join; const resolve = require('path').resolve; const inquirer = require('inquirer'); diff --git a/packages/kbn-plugin-helpers/tasks/build/build_action.test.js b/packages/kbn-plugin-helpers/tasks/build/build_action.test.js index 2364cca2542e7d..1d5d12ca00863a 100644 --- a/packages/kbn-plugin-helpers/tasks/build/build_action.test.js +++ b/packages/kbn-plugin-helpers/tasks/build/build_action.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const resolve = require('path').resolve; const fs = require('fs'); const del = require('del'); diff --git a/packages/kbn-plugin-helpers/tasks/build/create_build.js b/packages/kbn-plugin-helpers/tasks/build/create_build.js index 0058584acfadfa..e50291968fffab 100644 --- a/packages/kbn-plugin-helpers/tasks/build/create_build.js +++ b/packages/kbn-plugin-helpers/tasks/build/create_build.js @@ -1,6 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const join = require('path').join; const relative = require('path').relative; -const unlinkSync = require('fs').unlinkSync; +const { readFileSync, writeFileSync, unlinkSync, existsSync } = require('fs'); const execFileSync = require('child_process').execFileSync; const del = require('del'); const vfs = require('vinyl-fs'); @@ -29,6 +48,22 @@ function removeSymlinkDependencies(root) { }); } +// parse a ts config file +function parseTsconfig(pluginSourcePath, configPath) { + const ts = require(join(pluginSourcePath, 'node_modules', 'typescript')); + + const { error, config } = ts.parseConfigFileTextToJson( + configPath, + readFileSync(configPath, 'utf8') + ); + + if (error) { + throw error; + } + + return config; +} + module.exports = function createBuild( plugin, buildTarget, @@ -83,6 +118,45 @@ module.exports = function createBuild( options ); }) + .then(function() { + const buildConfigPath = join(buildRoot, 'tsconfig.json'); + + if (!existsSync(buildConfigPath)) { + return; + } + + if (!plugin.pkg.devDependencies.typescript) { + throw new Error( + 'Found tsconfig.json file in plugin but typescript is not a devDependency.' + ); + } + + // attempt to patch the extends path in the tsconfig file + const buildConfig = parseTsconfig(buildSource, buildConfigPath); + + if (buildConfig.extends) { + buildConfig.extends = join( + relative(buildRoot, buildSource), + buildConfig.extends + ); + + writeFileSync(buildConfigPath, JSON.stringify(buildConfig)); + } + + execFileSync( + join(buildSource, 'node_modules', '.bin', 'tsc'), + ['--pretty', 'true'], + { + cwd: buildRoot, + stdio: ['ignore', 'pipe', 'pipe'], + } + ); + + del.sync([ + join(buildRoot, '**', '*.{ts,tsx,d.ts}'), + join(buildRoot, 'tsconfig.json'), + ]); + }) .then(function() { const buildFiles = [relative(buildTarget, buildRoot) + '/**/*']; diff --git a/packages/kbn-plugin-helpers/tasks/build/create_build.test.js b/packages/kbn-plugin-helpers/tasks/build/create_build.test.js index 63065fb14040c1..b3a52827e59ef2 100644 --- a/packages/kbn-plugin-helpers/tasks/build/create_build.test.js +++ b/packages/kbn-plugin-helpers/tasks/build/create_build.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { resolve } = require('path'); const { readdirSync } = require('fs'); const del = require('del'); diff --git a/packages/kbn-plugin-helpers/tasks/build/create_package.js b/packages/kbn-plugin-helpers/tasks/build/create_package.js index e5423006fdb8a8..6df55fda902b04 100644 --- a/packages/kbn-plugin-helpers/tasks/build/create_package.js +++ b/packages/kbn-plugin-helpers/tasks/build/create_package.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const join = require('path').join; const relative = require('path').relative; const del = require('del'); diff --git a/packages/kbn-plugin-helpers/tasks/build/create_package.test.js b/packages/kbn-plugin-helpers/tasks/build/create_package.test.js index 1bec584c91ec16..c7c21f913fd6c0 100644 --- a/packages/kbn-plugin-helpers/tasks/build/create_package.test.js +++ b/packages/kbn-plugin-helpers/tasks/build/create_package.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { resolve } = require('path'); const { statSync } = require('fs'); const del = require('del'); diff --git a/packages/kbn-plugin-helpers/tasks/build/git_info.js b/packages/kbn-plugin-helpers/tasks/build/git_info.js index a0e52179c35961..e3b57719ebe84d 100644 --- a/packages/kbn-plugin-helpers/tasks/build/git_info.js +++ b/packages/kbn-plugin-helpers/tasks/build/git_info.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const execFileSync = require('child_process').execFileSync; module.exports = function gitInfo(rootPath) { diff --git a/packages/kbn-plugin-helpers/tasks/build/index.js b/packages/kbn-plugin-helpers/tasks/build/index.js index 41e0ad701a3b9a..b01a64c7f9be24 100644 --- a/packages/kbn-plugin-helpers/tasks/build/index.js +++ b/packages/kbn-plugin-helpers/tasks/build/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = require('./build_action'); diff --git a/packages/kbn-plugin-helpers/tasks/build/rewrite_package_json.js b/packages/kbn-plugin-helpers/tasks/build/rewrite_package_json.js index c0d7f9ea2441d8..7d20435436814e 100644 --- a/packages/kbn-plugin-helpers/tasks/build/rewrite_package_json.js +++ b/packages/kbn-plugin-helpers/tasks/build/rewrite_package_json.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const map = require('through2-map').obj; const gitInfo = require('./git_info'); diff --git a/packages/kbn-plugin-helpers/tasks/postinstall/index.js b/packages/kbn-plugin-helpers/tasks/postinstall/index.js index f35a19d195d1e4..9522e1e0e89982 100644 --- a/packages/kbn-plugin-helpers/tasks/postinstall/index.js +++ b/packages/kbn-plugin-helpers/tasks/postinstall/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const resolve = require('path').resolve; const statSync = require('fs').statSync; diff --git a/packages/kbn-plugin-helpers/tasks/start/index.js b/packages/kbn-plugin-helpers/tasks/start/index.js index 6a9f9603bbbbb0..b76e91fd5f2898 100644 --- a/packages/kbn-plugin-helpers/tasks/start/index.js +++ b/packages/kbn-plugin-helpers/tasks/start/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = require('./start_action'); diff --git a/packages/kbn-plugin-helpers/tasks/start/start_action.js b/packages/kbn-plugin-helpers/tasks/start/start_action.js index 88d893b8f7cb69..176000eb0dbe7f 100644 --- a/packages/kbn-plugin-helpers/tasks/start/start_action.js +++ b/packages/kbn-plugin-helpers/tasks/start/start_action.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const execFileSync = require('child_process').execFileSync; const { join } = require('path'); const split = require('argv-split'); diff --git a/packages/kbn-plugin-helpers/tasks/test/all/index.js b/packages/kbn-plugin-helpers/tasks/test/all/index.js index c0dd7b915543b0..0cdc615ee867fd 100644 --- a/packages/kbn-plugin-helpers/tasks/test/all/index.js +++ b/packages/kbn-plugin-helpers/tasks/test/all/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = require('./test_all_action'); diff --git a/packages/kbn-plugin-helpers/tasks/test/all/test_all_action.js b/packages/kbn-plugin-helpers/tasks/test/all/test_all_action.js index 1203242f02a291..da0b46e47a3d3c 100644 --- a/packages/kbn-plugin-helpers/tasks/test/all/test_all_action.js +++ b/packages/kbn-plugin-helpers/tasks/test/all/test_all_action.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = function testAllAction(plugin, run) { run('testServer'); run('testBrowser'); diff --git a/packages/kbn-plugin-helpers/tasks/test/browser/index.js b/packages/kbn-plugin-helpers/tasks/test/browser/index.js index a993b09562bfb5..972da4eca45186 100644 --- a/packages/kbn-plugin-helpers/tasks/test/browser/index.js +++ b/packages/kbn-plugin-helpers/tasks/test/browser/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = require('./test_browser_action'); diff --git a/packages/kbn-plugin-helpers/tasks/test/browser/test_browser_action.js b/packages/kbn-plugin-helpers/tasks/test/browser/test_browser_action.js index 8b5bb092e9004f..2fa89f0d84349c 100644 --- a/packages/kbn-plugin-helpers/tasks/test/browser/test_browser_action.js +++ b/packages/kbn-plugin-helpers/tasks/test/browser/test_browser_action.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const execFileSync = require('child_process').execFileSync; const winCmd = require('../../../lib/win_cmd'); diff --git a/packages/kbn-plugin-helpers/tasks/test/server/index.js b/packages/kbn-plugin-helpers/tasks/test/server/index.js index ac42bdcf7b1d73..b95d0321b04fe7 100644 --- a/packages/kbn-plugin-helpers/tasks/test/server/index.js +++ b/packages/kbn-plugin-helpers/tasks/test/server/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = require('./test_server_action'); diff --git a/packages/kbn-plugin-helpers/tasks/test/server/test_server_action.js b/packages/kbn-plugin-helpers/tasks/test/server/test_server_action.js index 1490ec1cc52971..f7faca1ee3c70b 100644 --- a/packages/kbn-plugin-helpers/tasks/test/server/test_server_action.js +++ b/packages/kbn-plugin-helpers/tasks/test/server/test_server_action.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const resolve = require('path').resolve; const delimiter = require('path').delimiter; const execFileSync = require('child_process').execFileSync; diff --git a/packages/kbn-pm/cli.js b/packages/kbn-pm/cli.js index 02681e6ccbd0df..2381910465b040 100644 --- a/packages/kbn-pm/cli.js +++ b/packages/kbn-pm/cli.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('./dist').run(process.argv.slice(2)); diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 10f791028ad24b..5fd05f6daecc36 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -11130,12 +11130,9 @@ Object.defineProperty(exports, "__esModule", { let parallelizeBatches = exports.parallelizeBatches = (() => { var _ref = _asyncToGenerator(function* (batches, fn) { for (const batch of batches) { - const running = batch.map(function (obj) { - return fn(obj); - }); // We need to make sure the entire batch has completed before we can move on // to the next batch - yield Promise.all(running); + yield parallelize(batch, fn); } }); @@ -11144,6 +11141,48 @@ let parallelizeBatches = exports.parallelizeBatches = (() => { }; })(); +let parallelize = exports.parallelize = (() => { + var _ref2 = _asyncToGenerator(function* (items, fn, concurrency = 4) { + if (items.length === 0) { + return; + } + return new Promise(function (resolve, reject) { + let scheduleItem = (() => { + var _ref3 = _asyncToGenerator(function* (item) { + activePromises++; + try { + yield fn(item); + activePromises--; + if (values.length > 0) { + // We have more work to do, so we schedule the next promise + scheduleItem(values.shift()); + } else if (activePromises === 0) { + // We have no more values left, and all items have completed, so we've + // completed all the work. + resolve(); + } + } catch (error) { + reject(error); + } + }); + + return function scheduleItem(_x5) { + return _ref3.apply(this, arguments); + }; + })(); + + let activePromises = 0; + const values = items.slice(0); + + values.splice(0, concurrency).map(scheduleItem); + }); + }); + + return function parallelize(_x3, _x4) { + return _ref2.apply(this, arguments); + }; +})(); + function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /***/ }), diff --git a/packages/kbn-pm/src/cli.ts b/packages/kbn-pm/src/cli.ts index df3e57305fda21..35498ba637fea0 100644 --- a/packages/kbn-pm/src/cli.ts +++ b/packages/kbn-pm/src/cli.ts @@ -1,17 +1,37 @@ -import getopts from 'getopts'; -import dedent from 'dedent'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import chalk from 'chalk'; +import dedent from 'dedent'; +import getopts from 'getopts'; import { resolve } from 'path'; import { commands } from './commands'; import { runCommand } from './run'; +import { log } from './utils/log'; function help() { const availableCommands = Object.keys(commands) .map(commandName => commands[commandName]) .map(command => `${command.name} - ${command.description}`); - console.log(dedent` + log.write(dedent` usage: kbn [] By default commands are run for Kibana itself, all packages in the 'packages/' @@ -35,7 +55,7 @@ export async function run(argv: string[]) { // starts forwarding the `--` directly to this script, see // https://github.com/yarnpkg/yarn/blob/b2d3e1a8fe45ef376b716d597cc79b38702a9320/src/cli/index.js#L174-L182 if (argv.includes('--')) { - console.log( + log.write( chalk.red( `Using "--" is not allowed, as it doesn't work with 'yarn kbn'.` ) @@ -45,9 +65,9 @@ export async function run(argv: string[]) { const options = getopts(argv, { alias: { + e: 'exclude', h: 'help', i: 'include', - e: 'exclude', }, }); @@ -69,7 +89,7 @@ export async function run(argv: string[]) { const command = commands[commandName]; if (command === undefined) { - console.log( + log.write( chalk.red(`[${commandName}] is not a valid command, see 'kbn --help'`) ); process.exit(1); diff --git a/packages/kbn-pm/src/commands/bootstrap.test.ts b/packages/kbn-pm/src/commands/bootstrap.test.ts index 7c9afd68bf7d90..307917e77d1ceb 100644 --- a/packages/kbn-pm/src/commands/bootstrap.test.ts +++ b/packages/kbn-pm/src/commands/bootstrap.test.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + jest.mock('../utils/scripts'); jest.mock('../utils/link_project_executables'); @@ -7,18 +26,18 @@ import { absolutePathSnapshotSerializer, stripAnsiSnapshotSerializer, } from '../test_helpers'; -import { BootstrapCommand } from './bootstrap'; -import { PackageJson } from '../utils/package_json'; +import { linkProjectExecutables } from '../utils/link_project_executables'; +import { IPackageJson } from '../utils/package_json'; import { Project } from '../utils/project'; import { buildProjectGraph } from '../utils/projects'; import { installInDir, runScriptInPackageStreaming } from '../utils/scripts'; -import { linkProjectExecutables } from '../utils/link_project_executables'; +import { BootstrapCommand } from './bootstrap'; const mockInstallInDir = installInDir as jest.Mock; const mockRunScriptInPackageStreaming = runScriptInPackageStreaming as jest.Mock; const mockLinkProjectExecutables = linkProjectExecutables as jest.Mock; -const createProject = (packageJson: PackageJson, path = '.') => +const createProject = (packageJson: IPackageJson, path = '.') => new Project( { name: 'kibana', @@ -31,7 +50,9 @@ const createProject = (packageJson: PackageJson, path = '.') => expect.addSnapshotSerializer(absolutePathSnapshotSerializer); expect.addSnapshotSerializer(stripAnsiSnapshotSerializer); -const noop = () => {}; +const noop = () => { + // noop +}; afterEach(() => { jest.resetAllMocks(); @@ -45,19 +66,19 @@ test('handles dependencies of dependencies', async () => { }); const foo = createProject( { - name: 'foo', dependencies: { bar: 'link:../bar', }, + name: 'foo', }, 'packages/foo' ); const bar = createProject( { - name: 'bar', dependencies: { baz: 'link:../baz', }, + name: 'bar', }, 'packages/bar' ); diff --git a/packages/kbn-pm/src/commands/bootstrap.ts b/packages/kbn-pm/src/commands/bootstrap.ts index db146dc73a6000..33e029aa256509 100644 --- a/packages/kbn-pm/src/commands/bootstrap.ts +++ b/packages/kbn-pm/src/commands/bootstrap.ts @@ -1,13 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import chalk from 'chalk'; -import { topologicallyBatchProjects } from '../utils/projects'; import { linkProjectExecutables } from '../utils/link_project_executables'; +import { log } from '../utils/log'; import { parallelizeBatches } from '../utils/parallelize'; -import { Command } from './'; +import { topologicallyBatchProjects } from '../utils/projects'; +import { ICommand } from './'; -export const BootstrapCommand: Command = { - name: 'bootstrap', +export const BootstrapCommand: ICommand = { description: 'Install dependencies and crosslink projects', + name: 'bootstrap', async run(projects, projectGraph, { options }) { const batchedProjects = topologicallyBatchProjects(projects, projectGraph); @@ -15,7 +35,7 @@ export const BootstrapCommand: Command = { const frozenLockfile = options['frozen-lockfile'] === true; const extraArgs = frozenLockfile ? ['--frozen-lockfile'] : []; - console.log(chalk.bold('\nRunning installs in topological order:')); + log.write(chalk.bold('\nRunning installs in topological order:')); for (const batch of batchedProjects) { for (const project of batch) { @@ -25,7 +45,7 @@ export const BootstrapCommand: Command = { } } - console.log( + log.write( chalk.bold('\nInstalls completed, linking package executables:\n') ); await linkProjectExecutables(projects, projectGraph); @@ -36,7 +56,7 @@ export const BootstrapCommand: Command = { * transpiled before they can be used. Ideally we shouldn't do this unless we * have to, as it will slow down the bootstrapping process. */ - console.log( + log.write( chalk.bold( '\nLinking executables completed, running `kbn:bootstrap` scripts\n' ) @@ -47,6 +67,6 @@ export const BootstrapCommand: Command = { } }); - console.log(chalk.green.bold('\nBootstrapping completed!\n')); + log.write(chalk.green.bold('\nBootstrapping completed!\n')); }, }; diff --git a/packages/kbn-pm/src/commands/clean.ts b/packages/kbn-pm/src/commands/clean.ts index 5d736fbc4eb163..8bbf781b576ed9 100644 --- a/packages/kbn-pm/src/commands/clean.ts +++ b/packages/kbn-pm/src/commands/clean.ts @@ -1,15 +1,35 @@ -import del from 'del'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import chalk from 'chalk'; -import { relative } from 'path'; +import del from 'del'; import ora from 'ora'; +import { relative } from 'path'; import { isDirectory } from '../utils/fs'; -import { Command } from './'; +import { log } from '../utils/log'; +import { ICommand } from './'; -export const CleanCommand: Command = { - name: 'clean', +export const CleanCommand: ICommand = { description: 'Remove the node_modules and target directories from all projects.', + name: 'clean', async run(projects, projectGraph, { rootPath }) { const directoriesToDelete = []; @@ -24,9 +44,9 @@ export const CleanCommand: Command = { } if (directoriesToDelete.length === 0) { - console.log(chalk.bold.green('\n\nNo directories to delete')); + log.write(chalk.bold.green('\n\nNo directories to delete')); } else { - console.log(chalk.bold.red('\n\nDeleting directories:\n')); + log.write(chalk.bold.red('\n\nDeleting directories:\n')); for (const dir of directoriesToDelete) { const deleting = del(dir, { force: true }); diff --git a/packages/kbn-pm/src/commands/index.ts b/packages/kbn-pm/src/commands/index.ts index 2ba4d52609af13..bf8e328c2975fa 100644 --- a/packages/kbn-pm/src/commands/index.ts +++ b/packages/kbn-pm/src/commands/index.ts @@ -1,19 +1,38 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { ProjectGraph, ProjectMap } from '../utils/projects'; -export interface CommandConfig { +export interface ICommandConfig { extraArgs: string[]; options: { [key: string]: any }; rootPath: string; } -export interface Command { +export interface ICommand { name: string; description: string; run: ( projects: ProjectMap, projectGraph: ProjectGraph, - config: CommandConfig + config: ICommandConfig ) => Promise; } @@ -22,7 +41,7 @@ import { CleanCommand } from './clean'; import { RunCommand } from './run'; import { WatchCommand } from './watch'; -export const commands: { [key: string]: Command } = { +export const commands: { [key: string]: ICommand } = { bootstrap: BootstrapCommand, clean: CleanCommand, run: RunCommand, diff --git a/packages/kbn-pm/src/commands/run.ts b/packages/kbn-pm/src/commands/run.ts index 575013ba3e3a9f..0d76aee602ec47 100644 --- a/packages/kbn-pm/src/commands/run.ts +++ b/packages/kbn-pm/src/commands/run.ts @@ -1,26 +1,46 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import chalk from 'chalk'; -import { topologicallyBatchProjects } from '../utils/projects'; +import { log } from '../utils/log'; import { parallelizeBatches } from '../utils/parallelize'; -import { Command } from './'; +import { topologicallyBatchProjects } from '../utils/projects'; +import { ICommand } from './'; -export const RunCommand: Command = { - name: 'run', +export const RunCommand: ICommand = { description: 'Run script defined in package.json in each package that contains that script.', + name: 'run', async run(projects, projectGraph, { extraArgs }) { const batchedProjects = topologicallyBatchProjects(projects, projectGraph); if (extraArgs.length === 0) { - console.log(chalk.red.bold('\nNo script specified')); + log.write(chalk.red.bold('\nNo script specified')); process.exit(1); } const scriptName = extraArgs[0]; const scriptArgs = extraArgs.slice(1); - console.log( + log.write( chalk.bold( `\nRunning script [${chalk.green( scriptName diff --git a/packages/kbn-pm/src/commands/watch.ts b/packages/kbn-pm/src/commands/watch.ts index 7c98cffbcd30fb..d7c2ab38b71915 100644 --- a/packages/kbn-pm/src/commands/watch.ts +++ b/packages/kbn-pm/src/commands/watch.ts @@ -1,8 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import chalk from 'chalk'; -import { topologicallyBatchProjects, ProjectMap } from '../utils/projects'; +import { log } from '../utils/log'; import { parallelizeBatches } from '../utils/parallelize'; +import { ProjectMap, topologicallyBatchProjects } from '../utils/projects'; import { waitUntilWatchIsReady } from '../utils/watch'; -import { Command } from './'; +import { ICommand } from './'; /** * Name of the script in the package/project package.json file to run during `kbn watch`. @@ -24,9 +44,9 @@ const kibanaProjectName = 'kibana'; * the `kbn:watch` script and eventually for the entire batch. Currently we support completion "markers" for * `webpack` and `tsc` only, for the rest we rely on predefined timeouts. */ -export const WatchCommand: Command = { - name: 'watch', +export const WatchCommand: ICommand = { description: 'Runs `kbn:watch` script for every project.', + name: 'watch', async run(projects, projectGraph) { const projectsToWatch: ProjectMap = new Map(); @@ -38,7 +58,7 @@ export const WatchCommand: Command = { } if (projectsToWatch.size === 0) { - console.log( + log.write( chalk.red( `\nThere are no projects to watch found. Make sure that projects define 'kbn:watch' script in 'package.json'.\n` ) @@ -47,7 +67,7 @@ export const WatchCommand: Command = { } const projectNames = Array.from(projectsToWatch.keys()); - console.log( + log.write( chalk.bold( chalk.green( `Running ${watchScriptName} scripts for [${projectNames.join(', ')}].` @@ -73,7 +93,7 @@ export const WatchCommand: Command = { pkg.runScriptStreaming(watchScriptName).stdout ); - console.log( + log.write( chalk.bold( `[${chalk.green( pkg.name diff --git a/packages/kbn-pm/src/config.ts b/packages/kbn-pm/src/config.ts index 6de265c336b704..3eb497033b3785 100644 --- a/packages/kbn-pm/src/config.ts +++ b/packages/kbn-pm/src/config.ts @@ -1,14 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve } from 'path'; -export type ProjectPathOptions = { +export interface IProjectPathOptions { 'skip-kibana-extra'?: boolean; - 'oss'?: boolean; -}; + oss?: boolean; +} /** * Returns all the paths where plugins are located */ -export function getProjectPaths(rootPath: string, options: ProjectPathOptions) { +export function getProjectPaths( + rootPath: string, + options: IProjectPathOptions +) { const skipKibanaExtra = Boolean(options['skip-kibana-extra']); const ossOnly = Boolean(options.oss); diff --git a/packages/kbn-pm/src/index.ts b/packages/kbn-pm/src/index.ts index 1b13e8af46d780..390dd5e2f67cb9 100644 --- a/packages/kbn-pm/src/index.ts +++ b/packages/kbn-pm/src/index.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { run } from './cli'; export { buildProductionProjects, diff --git a/packages/kbn-pm/src/production/build_production_projects.ts b/packages/kbn-pm/src/production/build_production_projects.ts index 7e107e24c134b6..211aef62997c21 100644 --- a/packages/kbn-pm/src/production/build_production_projects.ts +++ b/packages/kbn-pm/src/production/build_production_projects.ts @@ -1,22 +1,41 @@ -import del from 'del'; -import { relative, resolve, join } from 'path'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import copy from 'cpy'; +import del from 'del'; +import { join, relative, resolve } from 'path'; import { getProjectPaths } from '../config'; -import { - getProjects, - buildProjectGraph, - topologicallyBatchProjects, - ProjectMap, - includeTransitiveProjects, -} from '../utils/projects'; +import { isDirectory, isFile } from '../utils/fs'; +import { log } from '../utils/log'; import { createProductionPackageJson, - writePackageJson, readPackageJson, + writePackageJson, } from '../utils/package_json'; -import { isDirectory, isFile } from '../utils/fs'; import { Project } from '../utils/project'; +import { + buildProjectGraph, + getProjects, + includeTransitiveProjects, + topologicallyBatchProjects, +} from '../utils/projects'; export async function buildProductionProjects({ kibanaRoot, @@ -30,7 +49,7 @@ export async function buildProductionProjects({ const batchedProjects = topologicallyBatchProjects(projects, projectGraph); const projectNames = [...projects.values()].map(project => project.name); - console.log(`Preparing production build for [${projectNames.join(', ')}]`); + log.write(`Preparing production build for [${projectNames.join(', ')}]`); for (const batch of batchedProjects) { for (const project of batch) { @@ -99,9 +118,9 @@ async function copyToBuild( await copy(['**/*', '!node_modules/**'], buildProjectPath, { cwd: project.getIntermediateBuildDirectory(), - parents: true, - nodir: true, dot: true, + nodir: true, + parents: true, }); // If a project is using an intermediate build directory, we special-case our diff --git a/packages/kbn-pm/src/production/index.ts b/packages/kbn-pm/src/production/index.ts index fc69b957075b15..c25ee25dafe9fa 100644 --- a/packages/kbn-pm/src/production/index.ts +++ b/packages/kbn-pm/src/production/index.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { buildProductionProjects } from './build_production_projects'; export { prepareExternalProjectDependencies, diff --git a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/src/index.js b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/src/index.js index 60c722527da5c2..dd385cf4983349 100644 --- a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/src/index.js +++ b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/bar/src/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export default function(val) { diff --git a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/baz/code.js b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/baz/code.js index 4fe9fcd12d126c..b0d8ed315c9411 100644 --- a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/baz/code.js +++ b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/baz/code.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + console.log('@elastic/baz'); diff --git a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/src/index.js b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/src/index.js index bbe0c2322a4918..5611f96529819b 100644 --- a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/src/index.js +++ b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/foo/src/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import bar from '@elastic/bar'; // eslint-disable-line import/no-unresolved export default function(val) { diff --git a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/quux/quux.js b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/quux/quux.js index fb2364b23aa55c..fa5897b652843e 100644 --- a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/quux/quux.js +++ b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/quux/quux.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + console.log('@elastic/quux'); diff --git a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/shouldskip/src/index.js b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/shouldskip/src/index.js index bbe0c2322a4918..5611f96529819b 100644 --- a/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/shouldskip/src/index.js +++ b/packages/kbn-pm/src/production/integration_tests/__fixtures__/packages/shouldskip/src/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import bar from '@elastic/bar'; // eslint-disable-line import/no-unresolved export default function(val) { diff --git a/packages/kbn-pm/src/production/integration_tests/build_production_projects.test.ts b/packages/kbn-pm/src/production/integration_tests/build_production_projects.test.ts index 338a8fd1259a88..b17f28b74b1573 100644 --- a/packages/kbn-pm/src/production/integration_tests/build_production_projects.test.ts +++ b/packages/kbn-pm/src/production/integration_tests/build_production_projects.test.ts @@ -1,16 +1,35 @@ -import tempy from 'tempy'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import copy from 'cpy'; -import { resolve, relative, join } from 'path'; import globby from 'globby'; +import { join, resolve } from 'path'; +import tempy from 'tempy'; -import { buildProductionProjects } from '../build_production_projects'; -import { getProjects } from '../../utils/projects'; import { readPackageJson } from '../../utils/package_json'; +import { getProjects } from '../../utils/projects'; +import { buildProductionProjects } from '../build_production_projects'; -describe('kbn-pm production', function() { +describe('kbn-pm production', () => { test( 'builds and copies projects for production', - async function() { + async () => { const tmpDir = tempy.directory(); const buildRoot = tempy.directory(); const fixturesPath = resolve(__dirname, '__fixtures__'); @@ -18,9 +37,9 @@ describe('kbn-pm production', function() { // Copy all the test fixtures into a tmp dir, as we will be mutating them await copy(['**/*'], tmpDir, { cwd: fixturesPath, - parents: true, - nodir: true, dot: true, + nodir: true, + parents: true, }); const projects = await getProjects(tmpDir, ['.', './packages/*']); diff --git a/packages/kbn-pm/src/production/prepare_project_dependencies.test.ts b/packages/kbn-pm/src/production/prepare_project_dependencies.test.ts index 04f1eeb84e3312..694b412ee371fd 100644 --- a/packages/kbn-pm/src/production/prepare_project_dependencies.test.ts +++ b/packages/kbn-pm/src/production/prepare_project_dependencies.test.ts @@ -1,4 +1,23 @@ -import { resolve, join } from 'path'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { join, resolve } from 'path'; import { prepareExternalProjectDependencies } from './prepare_project_dependencies'; diff --git a/packages/kbn-pm/src/production/prepare_project_dependencies.ts b/packages/kbn-pm/src/production/prepare_project_dependencies.ts index a2a62d3942e6fc..b894d0683ae46e 100644 --- a/packages/kbn-pm/src/production/prepare_project_dependencies.ts +++ b/packages/kbn-pm/src/production/prepare_project_dependencies.ts @@ -1,5 +1,24 @@ -import { Project } from '../utils/project'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { isLinkDependency } from '../utils/package_json'; +import { Project } from '../utils/project'; /** * All external projects are located within `../kibana-extra/{plugin}` relative diff --git a/packages/kbn-pm/src/run.test.ts b/packages/kbn-pm/src/run.test.ts index 6e449f287f2833..7827498daa7ea9 100644 --- a/packages/kbn-pm/src/run.test.ts +++ b/packages/kbn-pm/src/run.test.ts @@ -1,7 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve } from 'path'; +import { ICommand, ICommandConfig } from './commands'; import { runCommand } from './run'; import { Project } from './utils/project'; -import { Command, CommandConfig } from './commands'; const rootPath = resolve(`${__dirname}/utils/__fixtures__/kibana`); @@ -25,12 +44,12 @@ function getExpectedProjectsAndGraph(runMock: any) { return { projects, graph }; } -let command: Command; -let config: CommandConfig; +let command: ICommand; +let config: ICommandConfig; beforeEach(() => { command = { - name: 'test name', description: 'test description', + name: 'test name', run: jest.fn(), }; @@ -41,7 +60,9 @@ beforeEach(() => { }; // Reduce the noise that comes from the run command. - jest.spyOn(console, 'log').mockImplementation(() => {}); + jest.spyOn(console, 'log').mockImplementation(() => { + // noop + }); }); test('passes all found projects to the command if no filter is specified', async () => { @@ -102,9 +123,9 @@ test('respects both `include` and `exclude` filters if specified at the same tim }); test('does not run command if all projects are filtered out', async () => { - let mockProcessExit = jest - .spyOn(process, 'exit') - .mockImplementation(() => {}); + const mockProcessExit = jest.spyOn(process, 'exit').mockImplementation(() => { + // noop + }); await runCommand(command, { ...config, diff --git a/packages/kbn-pm/src/run.ts b/packages/kbn-pm/src/run.ts index 40f875d32459b1..d64dd3a9045a6f 100644 --- a/packages/kbn-pm/src/run.ts +++ b/packages/kbn-pm/src/run.ts @@ -1,16 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import chalk from 'chalk'; -import wrapAnsi from 'wrap-ansi'; import indentString from 'indent-string'; +import wrapAnsi from 'wrap-ansi'; +import { ICommand, ICommandConfig } from './commands'; +import { getProjectPaths, IProjectPathOptions } from './config'; import { CliError } from './utils/errors'; -import { getProjects, buildProjectGraph } from './utils/projects'; +import { log } from './utils/log'; +import { buildProjectGraph, getProjects } from './utils/projects'; import { renderProjectsTree } from './utils/projects_tree'; -import { getProjectPaths, ProjectPathOptions } from './config'; -import { Command, CommandConfig } from './commands'; -export async function runCommand(command: Command, config: CommandConfig) { +export async function runCommand(command: ICommand, config: ICommandConfig) { try { - console.log( + log.write( chalk.bold( `Running [${chalk.green(command.name)}] command from [${chalk.yellow( config.rootPath @@ -20,7 +40,7 @@ export async function runCommand(command: Command, config: CommandConfig) { const projectPaths = getProjectPaths( config.rootPath, - config.options as ProjectPathOptions + config.options as IProjectPathOptions ); const projects = await getProjects(config.rootPath, projectPaths, { @@ -29,7 +49,7 @@ export async function runCommand(command: Command, config: CommandConfig) { }); if (projects.size === 0) { - console.log( + log.write( chalk.red( `There are no projects found. Double check project name(s) in '-i/--include' and '-e/--exclude' filters.\n` ) @@ -39,18 +59,18 @@ export async function runCommand(command: Command, config: CommandConfig) { const projectGraph = buildProjectGraph(projects); - console.log( + log.write( chalk.bold(`Found [${chalk.green(projects.size.toString())}] projects:\n`) ); - console.log(renderProjectsTree(config.rootPath, projects)); + log.write(renderProjectsTree(config.rootPath, projects)); await command.run(projects, projectGraph, config); } catch (e) { - console.log(chalk.bold.red(`\n[${command.name}] failed:\n`)); + log.write(chalk.bold.red(`\n[${command.name}] failed:\n`)); if (e instanceof CliError) { const msg = chalk.red(`CliError: ${e.message}\n`); - console.log(wrapAnsi(msg, 80)); + log.write(wrapAnsi(msg, 80)); const keys = Object.keys(e.meta); if (keys.length > 0) { @@ -59,11 +79,11 @@ export async function runCommand(command: Command, config: CommandConfig) { return `${key}: ${value}`; }); - console.log('Additional debugging info:\n'); - console.log(indentString(metaOutput.join('\n'), 3)); + log.write('Additional debugging info:\n'); + log.write(indentString(metaOutput.join('\n'), 3)); } } else { - console.log(e.stack); + log.write(e.stack); } process.exit(1); diff --git a/packages/kbn-pm/src/test_helpers/absolute_path_snapshot_serializer.ts b/packages/kbn-pm/src/test_helpers/absolute_path_snapshot_serializer.ts index 3628ebac5b75f3..96ce6fd1d919ab 100644 --- a/packages/kbn-pm/src/test_helpers/absolute_path_snapshot_serializer.ts +++ b/packages/kbn-pm/src/test_helpers/absolute_path_snapshot_serializer.ts @@ -1,5 +1,24 @@ -import { resolve, sep as pathSep } from 'path'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import cloneDeepWith from 'lodash.clonedeepwith'; +import { resolve, sep as pathSep } from 'path'; const repoRoot = resolve(__dirname, '../../../../'); @@ -16,8 +35,8 @@ const normalizePaths = (value: any) => { }); return { - didReplacement, clone, + didReplacement, }; }; diff --git a/packages/kbn-pm/src/test_helpers/index.ts b/packages/kbn-pm/src/test_helpers/index.ts index 09a71c475757f0..3498705d0f7700 100644 --- a/packages/kbn-pm/src/test_helpers/index.ts +++ b/packages/kbn-pm/src/test_helpers/index.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { absolutePathSnapshotSerializer, } from './absolute_path_snapshot_serializer'; diff --git a/packages/kbn-pm/src/test_helpers/strip_ansi_snapshot_serializer.ts b/packages/kbn-pm/src/test_helpers/strip_ansi_snapshot_serializer.ts index 31dc7b8cb89ff3..bf8bd129c0bbf6 100644 --- a/packages/kbn-pm/src/test_helpers/strip_ansi_snapshot_serializer.ts +++ b/packages/kbn-pm/src/test_helpers/strip_ansi_snapshot_serializer.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import hasAnsi from 'has-ansi'; import stripAnsi from 'strip-ansi'; diff --git a/packages/kbn-pm/src/utils/child_process.ts b/packages/kbn-pm/src/utils/child_process.ts index a221f69a430b19..eeefe5a26e1953 100644 --- a/packages/kbn-pm/src/utils/child_process.ts +++ b/packages/kbn-pm/src/utils/child_process.ts @@ -1,7 +1,26 @@ -import execa from 'execa'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import chalk from 'chalk'; -import logTransformer from 'strong-log-transformer'; +import execa from 'execa'; import logSymbols from 'log-symbols'; +import logTransformer from 'strong-log-transformer'; function generateColors() { const colorWheel = [ @@ -42,8 +61,8 @@ export function spawnStreaming( const color = nextColor(); const prefixedStdout = logTransformer({ tag: `${color.bold(prefix)}:` }); const prefixedStderr = logTransformer({ - tag: `${logSymbols.error} ${color.bold(prefix)}:`, mergeMultiline: true, + tag: `${logSymbols.error} ${color.bold(prefix)}:`, }); spawned.stdout.pipe(prefixedStdout).pipe(process.stdout); diff --git a/packages/kbn-pm/src/utils/errors.ts b/packages/kbn-pm/src/utils/errors.ts index 5901518df9cc5c..eaea3c86e67d84 100644 --- a/packages/kbn-pm/src/utils/errors.ts +++ b/packages/kbn-pm/src/utils/errors.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export class CliError extends Error { constructor(message: string, public readonly meta = {}) { super(message); diff --git a/packages/kbn-pm/src/utils/fs.ts b/packages/kbn-pm/src/utils/fs.ts index 46b5dbfbecfa8f..1f3a689eccd737 100644 --- a/packages/kbn-pm/src/utils/fs.ts +++ b/packages/kbn-pm/src/utils/fs.ts @@ -1,8 +1,27 @@ -import fs from 'fs'; -import { relative, dirname } from 'path'; -import { promisify } from 'util'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import cmdShimCb from 'cmd-shim'; +import fs from 'fs'; import mkdirpCb from 'mkdirp'; +import { dirname, relative } from 'path'; +import { promisify } from 'util'; const stat = promisify(fs.stat); const readFile = promisify(fs.readFile); diff --git a/packages/kbn-pm/src/utils/link_project_executables.test.ts b/packages/kbn-pm/src/utils/link_project_executables.test.ts index 3c33111be65bcd..1b8dc60ea44e5d 100644 --- a/packages/kbn-pm/src/utils/link_project_executables.test.ts +++ b/packages/kbn-pm/src/utils/link_project_executables.test.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + jest.mock('./fs'); import { resolve } from 'path'; @@ -15,10 +34,10 @@ const projectsByName = new Map([ 'foo', new Project( { - name: 'foo', dependencies: { bar: 'link:../bar', }, + name: 'foo', }, resolve(__dirname, 'foo') ), @@ -27,8 +46,8 @@ const projectsByName = new Map([ 'bar', new Project( { - name: 'bar', bin: 'bin/bar.js', + name: 'bar', }, resolve(__dirname, 'bar') ), @@ -37,10 +56,10 @@ const projectsByName = new Map([ 'baz', new Project( { - name: 'baz', devDependencies: { bar: 'link:../bar', }, + name: 'baz', }, resolve(__dirname, 'baz') ), @@ -82,7 +101,9 @@ describe('bin script points to a file', () => { const fs = require('./fs'); fs.isFile.mockReturnValue(true); - const logMock = jest.spyOn(console, 'log').mockImplementation(() => {}); + const logMock = jest.spyOn(console, 'log').mockImplementation(() => { + // noop + }); await linkProjectExecutables(projectsByName, projectGraph); logMock.mockRestore(); diff --git a/packages/kbn-pm/src/utils/link_project_executables.ts b/packages/kbn-pm/src/utils/link_project_executables.ts index c8efa5fab3554d..e2b515f4056c54 100644 --- a/packages/kbn-pm/src/utils/link_project_executables.ts +++ b/packages/kbn-pm/src/utils/link_project_executables.ts @@ -1,8 +1,28 @@ -import { resolve, relative, dirname, sep } from 'path'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { dirname, relative, resolve, sep } from 'path'; import chalk from 'chalk'; -import { createSymlink, isFile, chmod, mkdirp } from './fs'; +import { chmod, createSymlink, isFile, mkdirp } from './fs'; +import { log } from './log'; import { ProjectGraph, ProjectMap } from './projects'; /** @@ -39,7 +59,7 @@ export async function linkProjectExecutables( .split(sep) .join('/'); - console.log( + log.write( chalk`{dim [${project.name}]} ${name} -> {dim ${projectRelativePath}}` ); diff --git a/packages/kbn-pm/src/utils/log.ts b/packages/kbn-pm/src/utils/log.ts new file mode 100644 index 00000000000000..8e81e8592af47e --- /dev/null +++ b/packages/kbn-pm/src/utils/log.ts @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const log = { + /** + * Log something to the console. Ideally we would use a real logger in + * kbn-pm, but that's a pretty big change for now. + * @param ...args + */ + write(...args: any[]) { + // tslint:disable no-console + console.log(...args); + }, +}; diff --git a/packages/kbn-pm/src/utils/package_json.ts b/packages/kbn-pm/src/utils/package_json.ts index 0ec53b3f5e15db..cd62249eb54e4f 100644 --- a/packages/kbn-pm/src/utils/package_json.ts +++ b/packages/kbn-pm/src/utils/package_json.ts @@ -1,20 +1,44 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import readPkg from 'read-pkg'; import writePkg from 'write-pkg'; -import path from 'path'; -export type PackageJson = { [key: string]: any }; -export type PackageDependencies = { [key: string]: string }; -export type PackageScripts = { [key: string]: string }; +export interface IPackageJson { + [key: string]: any; +} +export interface IPackageDependencies { + [key: string]: string; +} +export interface IPackageScripts { + [key: string]: string; +} export function readPackageJson(dir: string) { return readPkg(dir, { normalize: false }); } -export function writePackageJson(path: string, json: PackageJson) { +export function writePackageJson(path: string, json: IPackageJson) { return writePkg(path, json); } -export const createProductionPackageJson = (pkgJson: PackageJson) => ({ +export const createProductionPackageJson = (pkgJson: IPackageJson) => ({ ...pkgJson, dependencies: transformDependencies(pkgJson.dependencies), }); @@ -31,8 +55,8 @@ export const isLinkDependency = (depVersion: string) => * will then _copy_ the `file:` dependencies into `node_modules` instead of * symlinking like we do in development. */ -export function transformDependencies(dependencies: PackageDependencies = {}) { - const newDeps: PackageDependencies = {}; +export function transformDependencies(dependencies: IPackageDependencies = {}) { + const newDeps: IPackageDependencies = {}; for (const name of Object.keys(dependencies)) { const depVersion = dependencies[name]; if (isLinkDependency(depVersion)) { diff --git a/packages/kbn-pm/src/utils/parallelize.test.ts b/packages/kbn-pm/src/utils/parallelize.test.ts index 10e5af4f17d1be..fa23ecbb8c1e78 100644 --- a/packages/kbn-pm/src/utils/parallelize.test.ts +++ b/packages/kbn-pm/src/utils/parallelize.test.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { parallelizeBatches } from './parallelize'; // As promises resolve async, we use this helper to wait for all promises that @@ -55,6 +74,39 @@ test('parallelizes batches', async () => { expect(completed).toEqual(['bar', 'foo', 'baz', 'parallelizeBatches']); }); +test('schedules at most 4 calls at the same time (concurrency)', async () => { + const foo = createPromiseWithResolve(); + const bar = createPromiseWithResolve(); + const baz = createPromiseWithResolve(); + const quux = createPromiseWithResolve(); + const foobar = createPromiseWithResolve(); + + const batches = [[foo, bar, baz, quux, foobar]]; + const parallelize = parallelizeBatches(batches, async obj => { + obj.called = true; + await obj.promise; + }); + + expect(foo.called).toBe(true); + expect(bar.called).toBe(true); + expect(baz.called).toBe(true); + expect(quux.called).toBe(true); + expect(foobar.called).toBe(false); + + foo.resolve(); + await tick(); + + expect(foobar.called).toBe(true); + + bar.resolve(); + baz.resolve(); + quux.resolve(); + foobar.resolve(); + await tick(); + + await expect(parallelize).resolves.toBe(undefined); +}); + test('rejects if any promise rejects', async () => { const foo = createPromiseWithResolve(); const bar = createPromiseWithResolve(); @@ -73,9 +125,9 @@ test('rejects if any promise rejects', async () => { function createPromiseWithResolve() { let resolve: (val?: any) => void; let reject: (err?: any) => void; - const promise = new Promise((_resolve, _reject) => { - resolve = _resolve; - reject = _reject; + const promise = new Promise((res, rej) => { + resolve = res; + reject = rej; }); return { promise, resolve: resolve!, reject: reject!, called: false }; } diff --git a/packages/kbn-pm/src/utils/parallelize.ts b/packages/kbn-pm/src/utils/parallelize.ts index 260b09df407669..dc202b8b6b2d39 100644 --- a/packages/kbn-pm/src/utils/parallelize.ts +++ b/packages/kbn-pm/src/utils/parallelize.ts @@ -1,12 +1,67 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export async function parallelizeBatches( - batches: Array, + batches: T[][], fn: (item: T) => Promise ) { for (const batch of batches) { - const running = batch.map(obj => fn(obj)); - // We need to make sure the entire batch has completed before we can move on // to the next batch - await Promise.all(running); + await parallelize(batch, fn); + } +} + +export async function parallelize( + items: T[], + fn: (item: T) => Promise, + concurrency = 4 +) { + if (items.length === 0) { + return; } + + return new Promise((resolve, reject) => { + let activePromises = 0; + const values = items.slice(0); + + async function scheduleItem(item: T) { + activePromises++; + + try { + await fn(item); + + activePromises--; + + if (values.length > 0) { + // We have more work to do, so we schedule the next promise + scheduleItem(values.shift()!); + } else if (activePromises === 0) { + // We have no more values left, and all items have completed, so we've + // completed all the work. + resolve(); + } + } catch (error) { + reject(error); + } + } + + values.splice(0, concurrency).map(scheduleItem); + }); } diff --git a/packages/kbn-pm/src/utils/project.test.ts b/packages/kbn-pm/src/utils/project.test.ts index 3e20dbce329b5c..9512777a7ed892 100644 --- a/packages/kbn-pm/src/utils/project.test.ts +++ b/packages/kbn-pm/src/utils/project.test.ts @@ -1,11 +1,30 @@ -import { resolve, join } from 'path'; - -import { PackageJson } from './package_json'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { join, resolve } from 'path'; + +import { IPackageJson } from './package_json'; import { Project } from './project'; const rootPath = resolve(`${__dirname}/__fixtures__/kibana`); -const createProjectWith = (packageJson: PackageJson, path = '') => +const createProjectWith = (packageJson: IPackageJson, path = '') => new Project( { name: 'kibana', @@ -25,12 +44,12 @@ describe('fromPath', () => { test('fields', async () => { const kibana = createProjectWith({ - scripts: { - test: 'jest', - }, dependencies: { foo: '1.2.3', }, + scripts: { + test: 'jest', + }, }); expect(kibana.name).toBe('kibana'); diff --git a/packages/kbn-pm/src/utils/project.ts b/packages/kbn-pm/src/utils/project.ts index 522164fa7e64a7..9d855f2ff55c8a 100644 --- a/packages/kbn-pm/src/utils/project.ts +++ b/packages/kbn-pm/src/utils/project.ts @@ -1,49 +1,69 @@ -import path from 'path'; -import { inspect } from 'util'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import chalk from 'chalk'; +import { relative, resolve as resolvePath } from 'path'; +import { inspect } from 'util'; +import { CliError } from './errors'; +import { log } from './log'; +import { + IPackageDependencies, + IPackageJson, + IPackageScripts, + isLinkDependency, + readPackageJson, +} from './package_json'; import { installInDir, runScriptInPackage, runScriptInPackageStreaming, } from './scripts'; -import { - PackageJson, - PackageDependencies, - PackageScripts, - isLinkDependency, - readPackageJson, -} from './package_json'; -import { CliError } from './errors'; -interface BuildConfig { +interface IBuildConfig { skip?: boolean; intermediateBuildDirectory?: string; } export class Project { - static async fromPath(path: string) { + public static async fromPath(path: string) { const pkgJson = await readPackageJson(path); return new Project(pkgJson, path); } - public readonly json: PackageJson; + public readonly json: IPackageJson; public readonly packageJsonLocation: string; public readonly nodeModulesLocation: string; public readonly targetLocation: string; public readonly path: string; - public readonly allDependencies: PackageDependencies; - public readonly productionDependencies: PackageDependencies; - public readonly devDependencies: PackageDependencies; - public readonly scripts: PackageScripts; + public readonly allDependencies: IPackageDependencies; + public readonly productionDependencies: IPackageDependencies; + public readonly devDependencies: IPackageDependencies; + public readonly scripts: IPackageScripts; - constructor(packageJson: PackageJson, projectPath: string) { + constructor(packageJson: IPackageJson, projectPath: string) { this.json = Object.freeze(packageJson); this.path = projectPath; - this.packageJsonLocation = path.resolve(this.path, 'package.json'); - this.nodeModulesLocation = path.resolve(this.path, 'node_modules'); - this.targetLocation = path.resolve(this.path, 'target'); + this.packageJsonLocation = resolvePath(this.path, 'package.json'); + this.nodeModulesLocation = resolvePath(this.path, 'node_modules'); + this.targetLocation = resolvePath(this.path, 'target'); this.productionDependencies = this.json.dependencies || {}; this.devDependencies = this.json.devDependencies || {}; @@ -59,9 +79,9 @@ export class Project { return this.json.name; } - ensureValidProjectDependency(project: Project) { + public ensureValidProjectDependency(project: Project) { const relativePathToProject = normalizePath( - path.relative(this.path, project.path) + relative(this.path, project.path) ); const versionInPackageJson = this.allDependencies[project.name]; @@ -73,9 +93,9 @@ export class Project { const updateMsg = 'Update its package.json to the expected value below.'; const meta = { - package: `${this.name} (${this.packageJsonLocation})`, - expected: `"${project.name}": "${expectedVersionInPackageJson}"`, actual: `"${project.name}": "${versionInPackageJson}"`, + expected: `"${project.name}": "${expectedVersionInPackageJson}"`, + package: `${this.name} (${this.packageJsonLocation})`, }; if (isLinkDependency(versionInPackageJson)) { @@ -95,7 +115,7 @@ export class Project { ); } - getBuildConfig(): BuildConfig { + public getBuildConfig(): IBuildConfig { return (this.json.kibana && this.json.kibana.build) || {}; } @@ -104,18 +124,18 @@ export class Project { * This config can be specified to only include the project's build artifacts * instead of everything located in the project directory. */ - getIntermediateBuildDirectory() { - return path.resolve( + public getIntermediateBuildDirectory() { + return resolvePath( this.path, this.getBuildConfig().intermediateBuildDirectory || '.' ); } - hasScript(name: string) { + public hasScript(name: string) { return name in this.scripts; } - getExecutables(): { [key: string]: string } { + public getExecutables(): { [key: string]: string } { const raw = this.json.bin; if (!raw) { @@ -124,14 +144,14 @@ export class Project { if (typeof raw === 'string') { return { - [this.name]: path.resolve(this.path, raw), + [this.name]: resolvePath(this.path, raw), }; } if (typeof raw === 'object') { const binsConfig: { [k: string]: string } = {}; for (const binName of Object.keys(raw)) { - binsConfig[binName] = path.resolve(this.path, raw[binName]); + binsConfig[binName] = resolvePath(this.path, raw[binName]); } return binsConfig; } @@ -140,14 +160,14 @@ export class Project { `[${this.name}] has an invalid "bin" field in its package.json, ` + `expected an object or a string`, { - package: `${this.name} (${this.packageJsonLocation})`, binConfig: inspect(raw), + package: `${this.name} (${this.packageJsonLocation})`, } ); } - async runScript(scriptName: string, args: string[] = []) { - console.log( + public async runScript(scriptName: string, args: string[] = []) { + log.write( chalk.bold( `\n\nRunning script [${chalk.green(scriptName)}] in [${chalk.green( this.name @@ -157,16 +177,16 @@ export class Project { return runScriptInPackage(scriptName, args, this); } - runScriptStreaming(scriptName: string, args: string[] = []) { + public runScriptStreaming(scriptName: string, args: string[] = []) { return runScriptInPackageStreaming(scriptName, args, this); } - hasDependencies() { + public hasDependencies() { return Object.keys(this.allDependencies).length > 0; } - async installDependencies({ extraArgs }: { extraArgs: string[] }) { - console.log( + public async installDependencies({ extraArgs }: { extraArgs: string[] }) { + log.write( chalk.bold( `\n\nInstalling dependencies in [${chalk.green(this.name)}]:\n` ) diff --git a/packages/kbn-pm/src/utils/projects.test.ts b/packages/kbn-pm/src/utils/projects.test.ts index bfa8fe96d08f12..f378319cfe1f5f 100644 --- a/packages/kbn-pm/src/utils/projects.test.ts +++ b/packages/kbn-pm/src/utils/projects.test.ts @@ -1,15 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve } from 'path'; +import { getProjectPaths } from '../config'; +import { Project } from './project'; import { - getProjects, buildProjectGraph, - topologicallyBatchProjects, + getProjects, includeTransitiveProjects, - ProjectMap, ProjectGraph, + ProjectMap, + topologicallyBatchProjects, } from './projects'; -import { Project } from './project'; -import { getProjectPaths } from '../config'; const rootPath = resolve(`${__dirname}/__fixtures__/kibana`); @@ -164,12 +183,12 @@ describe('#getProjects', () => { describe('#buildProjectGraph', () => { test('builds full project graph', async () => { - const projects = await getProjects(rootPath, [ + const allProjects = await getProjects(rootPath, [ '.', 'packages/*', '../plugins/*', ]); - const graph = buildProjectGraph(projects); + const graph = buildProjectGraph(allProjects); const expected: { [k: string]: string[] } = {}; for (const [projectName, projects] of graph.entries()) { diff --git a/packages/kbn-pm/src/utils/projects.ts b/packages/kbn-pm/src/utils/projects.ts index dbbadc32ef9b64..192c1be71350f0 100644 --- a/packages/kbn-pm/src/utils/projects.ts +++ b/packages/kbn-pm/src/utils/projects.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import globSync from 'glob'; import path from 'path'; import { promisify } from 'util'; @@ -9,12 +28,15 @@ const glob = promisify(globSync); export type ProjectMap = Map; export type ProjectGraph = Map; -export type ProjectsOptions = { include?: string[]; exclude?: string[] }; +export interface IProjectsOptions { + include?: string[]; + exclude?: string[]; +} export async function getProjects( rootPath: string, projectsPathsPatterns: string[], - { include = [], exclude = [] }: ProjectsOptions = {} + { include = [], exclude = [] }: IProjectsOptions = {} ) { const projects: ProjectMap = new Map(); diff --git a/packages/kbn-pm/src/utils/projects_tree.test.ts b/packages/kbn-pm/src/utils/projects_tree.test.ts index e2c5a43115ce0d..27c4f1d328424d 100644 --- a/packages/kbn-pm/src/utils/projects_tree.test.ts +++ b/packages/kbn-pm/src/utils/projects_tree.test.ts @@ -1,9 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve } from 'path'; +import { getProjectPaths } from '../config'; import { stripAnsiSnapshotSerializer } from '../test_helpers'; -import { renderProjectsTree } from './projects_tree'; import { getProjects } from './projects'; -import { getProjectPaths } from '../config'; +import { renderProjectsTree } from './projects_tree'; const rootPath = resolve(`${__dirname}/__fixtures__/kibana`); diff --git a/packages/kbn-pm/src/utils/projects_tree.ts b/packages/kbn-pm/src/utils/projects_tree.ts index 978fbbb0f19959..c3b2064ee6e49a 100644 --- a/packages/kbn-pm/src/utils/projects_tree.ts +++ b/packages/kbn-pm/src/utils/projects_tree.ts @@ -1,5 +1,24 @@ -import path from 'path'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import chalk from 'chalk'; +import path from 'path'; import { Project } from './project'; @@ -13,41 +32,44 @@ export function renderProjectsTree( return treeToString(createTreeStructure(projectsTree)); } -type Tree = { +interface ITree { name?: string; - children?: TreeChildren; -}; -interface TreeChildren extends Array {} + children?: ITreeChildren; +} +interface ITreeChildren extends Array {} type DirOrProjectName = string | typeof projectKey; -type ProjectsTree = Map; -interface ProjectsTreeValue extends ProjectsTree {} -function treeToString(tree: Tree) { - return [tree.name].concat(childrenToString(tree.children, '')).join('\n'); +interface IProjectsTree extends Map {} + +function treeToString(tree: ITree) { + return [tree.name].concat(childrenToStrings(tree.children, '')).join('\n'); } -function childrenToString(tree: TreeChildren | undefined, treePrefix: string) { +function childrenToStrings( + tree: ITreeChildren | undefined, + treePrefix: string +) { if (tree === undefined) { return []; } - let string: string[] = []; + let strings: string[] = []; tree.forEach((node, index) => { const isLastNode = tree.length - 1 === index; const nodePrefix = isLastNode ? '└── ' : '├── '; const childPrefix = isLastNode ? ' ' : '│ '; const childrenPrefix = treePrefix + childPrefix; - string.push(`${treePrefix}${nodePrefix}${node.name}`); - string = string.concat(childrenToString(node.children, childrenPrefix)); + strings.push(`${treePrefix}${nodePrefix}${node.name}`); + strings = strings.concat(childrenToStrings(node.children, childrenPrefix)); }); - return string; + return strings; } -function createTreeStructure(tree: ProjectsTree): Tree { +function createTreeStructure(tree: IProjectsTree): ITree { let name: string | undefined; - const children: TreeChildren = []; + const children: ITreeChildren = []; for (const [dir, project] of tree.entries()) { // This is a leaf node (aka a project) @@ -63,8 +85,8 @@ function createTreeStructure(tree: ProjectsTree): Tree { if (project.size === 1 && project.has(projectKey)) { const projectName = project.get(projectKey)! as string; children.push({ - name: dirOrProjectName(dir, projectName), children: [], + name: dirOrProjectName(dir, projectName), }); continue; } @@ -77,8 +99,8 @@ function createTreeStructure(tree: ProjectsTree): Tree { const projectName = subtree.name; children.push({ - name: dirOrProjectName(dir, projectName), children: subtree.children, + name: dirOrProjectName(dir, projectName), }); continue; } @@ -91,15 +113,15 @@ function createTreeStructure(tree: ProjectsTree): Tree { const newName = chalk.dim(path.join(dir.toString(), child.name!)); children.push({ - name: newName, children: child.children, + name: newName, }); continue; } children.push({ - name: chalk.dim(dir.toString()), children: subtree.children, + name: chalk.dim(dir.toString()), }); } @@ -113,7 +135,7 @@ function dirOrProjectName(dir: DirOrProjectName, projectName: string) { } function buildProjectsTree(rootPath: string, projects: Map) { - const tree: ProjectsTree = new Map(); + const tree: IProjectsTree = new Map(); for (const project of projects.values()) { if (rootPath === project.path) { @@ -128,7 +150,7 @@ function buildProjectsTree(rootPath: string, projects: Map) { } function addProjectToTree( - tree: ProjectsTree, + tree: IProjectsTree, pathParts: string[], project: Project ) { @@ -141,7 +163,7 @@ function addProjectToTree( tree.set(currentDir, new Map()); } - const subtree = tree.get(currentDir) as ProjectsTree; + const subtree = tree.get(currentDir) as IProjectsTree; addProjectToTree(subtree, rest, project); } } diff --git a/packages/kbn-pm/src/utils/scripts.ts b/packages/kbn-pm/src/utils/scripts.ts index a8637fc6f26f1f..a0cbd01fc811a2 100644 --- a/packages/kbn-pm/src/utils/scripts.ts +++ b/packages/kbn-pm/src/utils/scripts.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { spawn, spawnStreaming } from './child_process'; import { Project } from './project'; diff --git a/packages/kbn-pm/src/utils/watch.test.ts b/packages/kbn-pm/src/utils/watch.test.ts index 942500b9836363..3636b41af49a1c 100644 --- a/packages/kbn-pm/src/utils/watch.test.ts +++ b/packages/kbn-pm/src/utils/watch.test.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { EventEmitter } from 'events'; import { waitUntilWatchIsReady } from './watch'; diff --git a/packages/kbn-pm/src/utils/watch.ts b/packages/kbn-pm/src/utils/watch.ts index 0c254a7cc12861..5fbc0da39a60ae 100644 --- a/packages/kbn-pm/src/utils/watch.ts +++ b/packages/kbn-pm/src/utils/watch.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Observable, Subject } from 'rxjs'; /** @@ -14,7 +33,7 @@ const defaultHandlerReadinessTimeout = 2000; /** * Describes configurable watch options. */ -interface WatchOptions { +interface IWatchOptions { /** * Number of milliseconds to wait before we fall back to default watch handler. */ @@ -33,7 +52,7 @@ function getWatchHandlers( { handlerDelay = defaultHandlerDelay, handlerReadinessTimeout = defaultHandlerReadinessTimeout, - }: WatchOptions + }: IWatchOptions ) { const typescriptHandler = buildOutput$ .first(data => data.includes('$ tsc')) @@ -60,7 +79,7 @@ function getWatchHandlers( export function waitUntilWatchIsReady( stream: NodeJS.EventEmitter, - opts: WatchOptions = {} + opts: IWatchOptions = {} ) { const buildOutput$ = new Subject(); const onDataListener = (data: Buffer) => diff --git a/packages/kbn-pm/webpack.config.js b/packages/kbn-pm/webpack.config.js index 6030013a89b975..4fde5f88159b8b 100644 --- a/packages/kbn-pm/webpack.config.js +++ b/packages/kbn-pm/webpack.config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const path = require('path'); module.exports = { @@ -26,6 +45,12 @@ module.exports = { }, { loader: 'ts-loader', + options: { + compilerOptions: { + // enable esnext modules so webpack can do its thing better + module: 'esnext', + }, + }, }, ], exclude: /node_modules/, diff --git a/packages/kbn-system-loader/src/index.ts b/packages/kbn-system-loader/src/index.ts index eb88769ca20a7e..d7fcc9e209e314 100644 --- a/packages/kbn-system-loader/src/index.ts +++ b/packages/kbn-system-loader/src/index.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { SystemLoader } from './system_loader'; export { System } from './system'; export { KibanaSystem } from './system_types'; diff --git a/packages/kbn-system-loader/src/sorted_systems.ts b/packages/kbn-system-loader/src/sorted_systems.ts index 75880ed2d22232..ab4ef397dd7360 100644 --- a/packages/kbn-system-loader/src/sorted_systems.ts +++ b/packages/kbn-system-loader/src/sorted_systems.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { System } from './system'; import { SystemName } from './system_types'; import { topologicalSort } from './topological_sort'; diff --git a/packages/kbn-system-loader/src/system.test.ts b/packages/kbn-system-loader/src/system.test.ts index 212672a6ed3270..d4267f82e85ae3 100644 --- a/packages/kbn-system-loader/src/system.test.ts +++ b/packages/kbn-system-loader/src/system.test.ts @@ -1,16 +1,41 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* tslint:disable max-classes-per-file */ + import { System } from './system'; import { KibanaSystem } from './system_types'; test('can get exposed values after starting', () => { - type CoreType = { bar: string }; - type DepsType = { quux: string }; - type ExposedType = { - core: CoreType; - deps: DepsType; - }; + interface ICoreType { + bar: string; + } + interface IDepsType { + quux: string; + } + interface IExposedType { + core: ICoreType; + deps: IDepsType; + } - class FooSystem extends KibanaSystem { - start() { + class FooSystem extends KibanaSystem { + public start() { return { core: this.kibana, deps: this.deps, @@ -39,7 +64,7 @@ test('can get exposed values after starting', () => { test('throws if start returns a promise', () => { class FooSystem extends KibanaSystem { - async start() { + public async start() { return 'foo'; } } @@ -55,9 +80,11 @@ test('throws if start returns a promise', () => { test('throws if stop returns a promise', () => { class FooSystem extends KibanaSystem { - start() {} + public start() { + // noop + } - async stop() { + public async stop() { return 'stop'; } } diff --git a/packages/kbn-system-loader/src/system.ts b/packages/kbn-system-loader/src/system.ts index 40744133ff29d3..77ab50051304c9 100644 --- a/packages/kbn-system-loader/src/system.ts +++ b/packages/kbn-system-loader/src/system.ts @@ -1,9 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { - SystemsType, - SystemName, - SystemMetadata, - KibanaSystemClassStatic, + IKibanaSystemClassStatic, + ISystemMetadata, + ISystemsType, KibanaSystem, + SystemName, } from './system_types'; function isPromise(obj: any) { @@ -12,45 +31,45 @@ function isPromise(obj: any) { ); } -export class System { - readonly name: SystemName; - readonly dependencies: SystemName[]; - readonly metadata?: M; +export class System { + public readonly name: SystemName; + public readonly dependencies: SystemName[]; + public readonly metadata?: M; - private readonly _systemClass: KibanaSystemClassStatic; - private _systemInstance?: KibanaSystem; - private _exposedValues?: E; + private readonly systemClass: IKibanaSystemClassStatic; + private systemInstance?: KibanaSystem; + private exposedValues?: E; constructor( name: SystemName, config: { metadata?: M; dependencies?: SystemName[]; - implementation: KibanaSystemClassStatic; + implementation: IKibanaSystemClassStatic; } ) { this.name = name; this.dependencies = config.dependencies || []; this.metadata = config.metadata; - this._systemClass = config.implementation; + this.systemClass = config.implementation; } - getExposedValues(): E { - if (this._systemInstance === undefined) { + public getExposedValues(): E { + if (this.systemInstance === undefined) { throw new Error( 'trying to get the exposed value of a system that is NOT running' ); } - return this._exposedValues!; + return this.exposedValues!; } - start(kibanaValues: C, dependenciesValues: D) { - this._systemInstance = new this._systemClass( + public start(kibanaValues: C, dependenciesValues: D) { + this.systemInstance = new this.systemClass( kibanaValues, dependenciesValues ); - const exposedValues = this._systemInstance.start(); + const exposedValues = this.systemInstance.start(); if (isPromise(exposedValues)) { throw new Error( @@ -60,15 +79,15 @@ export class System { ); } - this._exposedValues = + this.exposedValues = exposedValues === undefined ? ({} as E) : exposedValues; } - stop() { - const stoppedResponse = this._systemInstance && this._systemInstance.stop(); + public stop() { + const stoppedResponse = this.systemInstance && this.systemInstance.stop(); - this._exposedValues = undefined; - this._systemInstance = undefined; + this.exposedValues = undefined; + this.systemInstance = undefined; if (isPromise(stoppedResponse)) { throw new Error( diff --git a/packages/kbn-system-loader/src/system_loader.test.ts b/packages/kbn-system-loader/src/system_loader.test.ts index a2c257fa25660c..31552ae514d29d 100644 --- a/packages/kbn-system-loader/src/system_loader.test.ts +++ b/packages/kbn-system-loader/src/system_loader.test.ts @@ -1,44 +1,72 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* tslint:disable max-classes-per-file */ + import { System } from './system'; +import { KibanaSystemApiFactory, SystemLoader } from './system_loader'; import { KibanaSystem } from './system_types'; -import { SystemLoader, KibanaSystemApiFactory } from './system_loader'; // To make types simpler in the tests type CoreType = void; -const createCoreValues = () => {}; +const createCoreValues = () => { + // noop +}; test('starts system with core api', () => { expect.assertions(1); - type KibanaCoreApi = { fromCore: boolean; name: string }; - type Metadata = { configPath?: string }; + interface IKibanaCoreApi { + fromCore: boolean; + name: string; + } + interface IMetadata { + configPath?: string; + } - class FooSystem extends KibanaSystem { - start() { + class FooSystem extends KibanaSystem { + public start() { expect(this.kibana).toEqual({ - name: 'foo', fromCore: true, metadata: { configPath: 'config.path.foo', }, + name: 'foo', }); } } const foo = new System('foo', { + implementation: FooSystem, metadata: { configPath: 'config.path.foo', }, - implementation: FooSystem, }); - const createSystemApi: KibanaSystemApiFactory = ( + const createSystemApi: KibanaSystemApiFactory = ( name, metadata ) => { return { - name, - metadata, fromCore: true, + metadata, + name, }; }; @@ -51,22 +79,22 @@ test('starts system with core api', () => { test('system can expose a value', () => { expect.assertions(1); - type Foo = { + interface IFoo { foo: { value: string; }; - }; + } - class FooSystem extends KibanaSystem { - start() { + class FooSystem extends KibanaSystem { + public start() { return { value: 'my-value', }; } } - class BarSystem extends KibanaSystem { - start() { + class BarSystem extends KibanaSystem { + public start() { expect(this.deps.foo).toEqual({ value: 'my-value' }); } } @@ -89,22 +117,22 @@ test('system can expose a value', () => { test('system can expose a function', () => { expect.assertions(2); - type Foo = { + interface IFoo { foo: { fn: (val: string) => string; }; - }; + } - class FooSystem extends KibanaSystem { - start(): Foo['foo'] { + class FooSystem extends KibanaSystem { + public start(): IFoo['foo'] { return { fn: val => `test-${val}`, }; } } - class BarSystem extends KibanaSystem { - start() { + class BarSystem extends KibanaSystem { + public start() { expect(this.deps.foo).toBeDefined(); expect(this.deps.foo.fn('some-value')).toBe('test-some-value'); } @@ -128,36 +156,36 @@ test('system can expose a function', () => { test('can expose value with same name across multiple systems', () => { expect.assertions(2); - type Foo = { + interface IFoo { foo: { value: string; }; - }; + } - type Bar = { + interface IBar { bar: { value: string; }; - }; + } - class FooSystem extends KibanaSystem { - start(): Foo['foo'] { + class FooSystem extends KibanaSystem { + public start(): IFoo['foo'] { return { value: 'value-foo', }; } } - class BarSystem extends KibanaSystem { - start(): Bar['bar'] { + class BarSystem extends KibanaSystem { + public start(): IBar['bar'] { return { value: 'value-bar', }; } } - class QuuxSystem extends KibanaSystem { - start() { + class QuuxSystem extends KibanaSystem { + public start() { expect(this.deps.foo).toEqual({ value: 'value-foo' }); expect(this.deps.bar).toEqual({ value: 'value-bar' }); } @@ -186,32 +214,36 @@ test('can expose value with same name across multiple systems', () => { test('receives values from dependencies but not transitive dependencies', () => { expect.assertions(3); - type Grandchild = { + interface IGrandchild { grandchild: { value: string; }; - }; + } - type Child = { + interface IChild { child: { value: string; }; - }; + } class GrandchildSystem extends KibanaSystem< CoreType, {}, - Grandchild['grandchild'] + IGrandchild['grandchild'] > { - start() { + public start() { return { value: 'grandchild', }; } } - class ChildSystem extends KibanaSystem { - start() { + class ChildSystem extends KibanaSystem< + CoreType, + IGrandchild, + IChild['child'] + > { + public start() { expect(this.deps.grandchild).toEqual({ value: 'grandchild' }); return { @@ -220,8 +252,8 @@ test('receives values from dependencies but not transitive dependencies', () => } } - class ParentSystem extends KibanaSystem { - start() { + class ParentSystem extends KibanaSystem { + public start() { expect(this.deps.child).toEqual({ value: 'child' }); expect(this.deps.grandchild).toBeUndefined(); } @@ -251,24 +283,24 @@ test('receives values from dependencies but not transitive dependencies', () => test('keeps reference on registered value', () => { expect.assertions(1); - type Child = { + interface IChild { child: { value: {}; }; - }; + } const myRef = {}; - class ChildSystem extends KibanaSystem { - start() { + class ChildSystem extends KibanaSystem { + public start() { return { value: myRef, }; } } - class ParentSystem extends KibanaSystem { - start() { + class ParentSystem extends KibanaSystem { + public start() { expect(this.deps.child.value).toBe(myRef); } } @@ -291,15 +323,15 @@ test('keeps reference on registered value', () => { test('can register multiple values in single system', () => { expect.assertions(1); - type Child = { + interface IChild { child: { value1: number; value2: number; }; - }; + } - class ChildSystem extends KibanaSystem { - start() { + class ChildSystem extends KibanaSystem { + public start() { return { value1: 1, value2: 2, @@ -307,8 +339,8 @@ test('can register multiple values in single system', () => { } } - class ParentSystem extends KibanaSystem { - start() { + class ParentSystem extends KibanaSystem { + public start() { expect(this.deps.child).toEqual({ value1: 1, value2: 2, @@ -333,7 +365,9 @@ test('can register multiple values in single system', () => { test("throws if starting a system that depends on a system that's not present", () => { class FooSystem extends KibanaSystem { - start() {} + public start() { + // noop + } } const foo = new System('foo', { @@ -352,7 +386,9 @@ test("throws if starting a system that depends on a system that's not present", test("throws if adding that has the same name as a system that's already added", () => { class FooSystem extends KibanaSystem { - start() {} + public start() { + // noop + } } const foo = new System('foo', { @@ -371,19 +407,19 @@ test('stops systems in reverse order of their starting order', () => { const events: string[] = []; class FooSystem extends KibanaSystem { - start() { + public start() { events.push('start foo'); } - stop() { + public stop() { events.push('stop foo'); } } class BarSystem extends KibanaSystem { - start() { + public start() { events.push('start bar'); } - stop() { + public stop() { events.push('stop bar'); } } @@ -409,18 +445,18 @@ test('stops systems in reverse order of their starting order', () => { test('can add systems before adding its dependencies', () => { expect.assertions(1); - type Foo = { + interface IFoo { foo: string; - }; + } - class FooSystem extends KibanaSystem { - start() { + class FooSystem extends KibanaSystem { + public start() { return 'value'; } } - class BarSystem extends KibanaSystem { - start() { + class BarSystem extends KibanaSystem { + public start() { expect(this.deps.foo).toBe('value'); } } @@ -447,13 +483,13 @@ test('can add multiple system specs at the same time', () => { const spy = jest.fn(); class FooSystem extends KibanaSystem { - start() { + public start() { spy(); } } class BarSystem extends KibanaSystem { - start() { + public start() { spy(); } } diff --git a/packages/kbn-system-loader/src/system_loader.ts b/packages/kbn-system-loader/src/system_loader.ts index 439c1d1a16f71a..2bd628a2f9a680 100644 --- a/packages/kbn-system-loader/src/system_loader.ts +++ b/packages/kbn-system-loader/src/system_loader.ts @@ -1,15 +1,34 @@ -import { System } from './system'; -import { SystemName, SystemMetadata, SystemsType } from './system_types'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { getSortedSystemNames } from './sorted_systems'; +import { System } from './system'; +import { ISystemMetadata, ISystemsType, SystemName } from './system_types'; export type KibanaSystemApiFactory = ( name: SystemName, metadata?: M ) => C; -export class SystemLoader { - private readonly _systems = new Map>(); - private _startedSystems: SystemName[] = []; +export class SystemLoader { + private readonly systems = new Map>(); + private startedSystems: SystemName[] = []; constructor( /** @@ -17,37 +36,54 @@ export class SystemLoader { * information about a system before it's started, and the return value will * be injected into the system at startup. */ - private readonly _kibanaSystemApiFactory: KibanaSystemApiFactory + private readonly kibanaSystemApiFactory: KibanaSystemApiFactory ) {} - addSystems(systemSpecs: System[]) { + public addSystems(systemSpecs: Array>) { systemSpecs.forEach(systemSpec => { this.addSystem(systemSpec); }); } - addSystem(system: System) { - if (this._systems.has(system.name)) { + public addSystem( + system: System + ) { + if (this.systems.has(system.name)) { throw new Error(`a system named [${system.name}] has already been added`); } - this._systems.set(system.name, system); + this.systems.set(system.name, system); } - startSystems() { + public startSystems() { this._ensureAllSystemDependenciesCanBeResolved(); - getSortedSystemNames(this._systems) - .map(systemName => this._systems.get(systemName)!) + getSortedSystemNames(this.systems) + .map(systemName => this.systems.get(systemName)!) .forEach(systemSpec => { this.startSystem(systemSpec); }); } + /** + * Stop all systems in the reverse order of when they were started + */ + public stopSystems() { + this.startedSystems + .map(systemName => this.systems.get(systemName)!) + .reverse() + .forEach(system => { + system.stop(); + this.systems.delete(system.name); + }); + + this.startedSystems = []; + } + private _ensureAllSystemDependenciesCanBeResolved() { - for (const [systemName, system] of this._systems) { + for (const [systemName, system] of this.systems) { for (const systemDependency of system.dependencies) { - if (!this._systems.has(systemDependency)) { + if (!this.systems.has(systemDependency)) { throw new Error( `System [${systemName}] depends on [${systemDependency}], which is not present` ); @@ -56,38 +92,23 @@ export class SystemLoader { } } - private startSystem( + private startSystem( system: System ) { const dependenciesValues = {} as D; for (const dependency of system.dependencies) { - dependenciesValues[dependency] = this._systems + dependenciesValues[dependency] = this.systems .get(dependency)! .getExposedValues(); } - const kibanaSystemApi = this._kibanaSystemApiFactory( + const kibanaSystemApi = this.kibanaSystemApiFactory( system.name, system.metadata ); system.start(kibanaSystemApi, dependenciesValues); - this._startedSystems.push(system.name); - } - - /** - * Stop all systems in the reverse order of when they were started - */ - stopSystems() { - this._startedSystems - .map(systemName => this._systems.get(systemName)!) - .reverse() - .forEach(system => { - system.stop(); - this._systems.delete(system.name); - }); - - this._startedSystems = []; + this.startedSystems.push(system.name); } } diff --git a/packages/kbn-system-loader/src/system_types.ts b/packages/kbn-system-loader/src/system_types.ts index ba825885f3ccb9..6322ba98cae98f 100644 --- a/packages/kbn-system-loader/src/system_types.ts +++ b/packages/kbn-system-loader/src/system_types.ts @@ -1,18 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export type SystemName = string; -export type SystemMetadata = { +export interface ISystemMetadata { [key: string]: any; -}; +} -export type SystemsType = { +export interface ISystemsType { [systemName: string]: any; -}; +} -export abstract class KibanaSystem { +export abstract class KibanaSystem { constructor(readonly kibana: C, readonly deps: D) {} - abstract start(): E; + public abstract start(): E; - stop() { + public stop() { // default implementation of stop does nothing } } @@ -27,6 +46,6 @@ export abstract class KibanaSystem { * * See https://www.typescriptlang.org/docs/handbook/interfaces.html#difference-between-the-static-and-instance-sides-of-classes */ -export interface KibanaSystemClassStatic { +export interface IKibanaSystemClassStatic { new (kibana: C, deps: D): KibanaSystem; } diff --git a/packages/kbn-system-loader/src/topological_sort.test.ts b/packages/kbn-system-loader/src/topological_sort.test.ts index 9fdfa850331c6a..d3cf67388e5077 100644 --- a/packages/kbn-system-loader/src/topological_sort.test.ts +++ b/packages/kbn-system-loader/src/topological_sort.test.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { topologicalSort } from './topological_sort'; test('returns a topologically ordered sequence', () => { @@ -8,7 +27,7 @@ test('returns a topologically ordered sequence', () => { ['d', ['a']], ]); - let sorted = topologicalSort(nodes); + const sorted = topologicalSort(nodes); expect(sorted).toBeDefined(); @@ -23,7 +42,7 @@ test('handles multiple "roots" with no deps', () => { ['d', ['a']], ]); - let sorted = topologicalSort(nodes); + const sorted = topologicalSort(nodes); expect(sorted).toBeDefined(); diff --git a/packages/kbn-system-loader/src/topological_sort.ts b/packages/kbn-system-loader/src/topological_sort.ts index 557a79933eba3a..673d12ec55740f 100644 --- a/packages/kbn-system-loader/src/topological_sort.ts +++ b/packages/kbn-system-loader/src/topological_sort.ts @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * A topological ordering is possible if and only if the graph has no directed * cycles, that is, if it is a directed acyclic graph (DAG). If the input cannot diff --git a/packages/kbn-system-loader/tsconfig.json b/packages/kbn-system-loader/tsconfig.json index f9a3362e099349..c23b6635a5c19e 100644 --- a/packages/kbn-system-loader/tsconfig.json +++ b/packages/kbn-system-loader/tsconfig.json @@ -1,8 +1,6 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "module": "commonjs", - "target": "es2017", "declaration": true, "outDir": "./target" }, diff --git a/packages/kbn-test-subj-selector/index.js b/packages/kbn-test-subj-selector/index.js index e3cfbb03d55b0f..c92d4b8f80fc2e 100755 --- a/packages/kbn-test-subj-selector/index.js +++ b/packages/kbn-test-subj-selector/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function seletorToTerms(selector) { return selector .replace(/\s*&\s*/g, '&') // remove all whitespace around joins diff --git a/packages/kbn-test-subj-selector/test/index.js b/packages/kbn-test-subj-selector/test/index.js index 2fe0834fb84d10..3ffeef96c7cda7 100755 --- a/packages/kbn-test-subj-selector/test/index.js +++ b/packages/kbn-test-subj-selector/test/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const testSubjSelector = require('../'); const expect = require('expect.js'); diff --git a/packages/kbn-test/.babelrc b/packages/kbn-test/.babelrc new file mode 100644 index 00000000000000..7da72d17791281 --- /dev/null +++ b/packages/kbn-test/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@kbn/babel-preset/node_preset"] +} diff --git a/packages/kbn-test/README.md b/packages/kbn-test/README.md new file mode 100644 index 00000000000000..3159e5c2492b4d --- /dev/null +++ b/packages/kbn-test/README.md @@ -0,0 +1,39 @@ +Kibana Testing Library +====================== + +The @kbn/test package provides ways to run tests. Currently only functional testing is provided by this library, with unit and other testing possibly added here. + +Functional Testing +------------------- + +### Dependencies + +Functional testing methods exist in the `src/functional_tests` directory. They depend on the Functional Test Runner, which is found in [`{KIBANA_ROOT}/src/functional_test_runner`](../../src/functional_test_runner). Ideally libraries provided by kibana packages such as this one should not depend on kibana source code that lives in [`{KIBANA_ROOT}/src`](../../src). The goal is to start pulling test and development utilities out into packages so they can be used across Kibana and plugins. Accordingly the Functional Test Runner itself will be pulled out into a package (or part of a package), and this package's dependence on it will not be an issue. + +### Exposed methods + +#### runTests(configPaths: Array) +For each config file specified in configPaths, starts Elasticsearch and Kibana once, runs tests specified in that config file, and shuts down Elasticsearch and Kibana once completed. (Repeats for every config file.) + +`configPaths`: array of strings, each an absolute path to a config file that looks like [this](../../test/functional/config.js), following the config schema specified [here](../../src/functional_test_runner/lib/config/schema.js). + +Internally the method that starts Elasticsearch comes from [kbn-es](../../packages/kbn-es). + +#### startServers(configPath: string) +Starts Elasticsearch and Kibana servers given a specified config. + +`configPath`: absolute path to a config file that looks like [this](../../test/functional/config.js), following the config schema specified [here](../../src/functional_test_runner/lib/config/schema.js). + +Allows users to start another process to run just the tests while keeping the servers running with this method. Start servers _and_ run tests using the same config file ([see how](../../scripts/README.md)). + +## Rationale + +### Single config per setup + +We think it makes sense to specify the tests to run along with the particular server configuration for Elasticsearch and Kibana servers, because the tests expect a particular configuration. For example, saml api integration tests expect certain xml files to exist in Elasticsearch's config directory, and certain saml specific options to be passed in via the command line (or alternatively via the `.yml` config file) to both Elasticsearch and Kibana. It makes sense to keep all these config options together with the list of test files. + +### Multiple configs running in succession + +We also think it makes sense to have a test runner intelligently (but simply) start servers, run tests, tear down servers, and repeat for each config, uninterrupted. There's nothing special about each kind of config that specifies running some set of functional tests against some kind of Elasticsearch/Kibana servers. There doesn't need to be a separate job to run each kind of setup/test/teardown. These can all be orchestrated sequentially via the current `runTests` implementation. This is how we envision tests to run on CI. + +This inherently means that grouping test files in configs matters, such that a group of test files that depends on a particular server config appears together in that config's `testFiles` list. Given how quickly and easily we can start servers using [@kbn/es](../../packages/kbn-es), it should not impact performance to logically group tests by domain even if multiple groups of tests share the same server config. We can think about how to group test files together across domains when that time comes. diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json new file mode 100644 index 00000000000000..33322774cfd29a --- /dev/null +++ b/packages/kbn-test/package.json @@ -0,0 +1,27 @@ +{ + "name": "@kbn/test", + "main": "./target/index.js", + "version": "1.0.0", + "license": "Apache-2.0", + "private": true, + "scripts": { + "build": "babel src --out-dir target", + "kbn:bootstrap": "yarn build", + "kbn:watch": "yarn build --watch" + }, + "devDependencies": { + "@kbn/babel-preset": "link:../kbn-babel-preset", + "@kbn/dev-utils": "link:../kbn-dev-utils", + "babel-cli": "^6.26.0" + }, + "dependencies": { + "chalk": "^2.4.1", + "dedent": "^0.7.0", + "getopts": "^2.0.6", + "glob": "^7.1.2", + "rxjs": "^5.4.3", + "tar-fs": "^1.16.2", + "tmp": "^0.0.33", + "zlib": "^1.0.5" + } +} diff --git a/src/test_utils/es/es_test_cluster.js b/packages/kbn-test/src/es/es_test_cluster.js similarity index 64% rename from src/test_utils/es/es_test_cluster.js rename to packages/kbn-test/src/es/es_test_cluster.js index d3eaedc5720e50..8ff7a0efefaf65 100644 --- a/src/test_utils/es/es_test_cluster.js +++ b/packages/kbn-test/src/es/es_test_cluster.js @@ -1,27 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve } from 'path'; -import { get } from 'lodash'; import { format } from 'url'; -import elasticsearch from 'elasticsearch'; +import { get } from 'lodash'; import toPath from 'lodash/internal/toPath'; import { Cluster } from '@kbn/es'; import { esTestConfig } from './es_test_config'; import { rmrfSync } from './rmrf_sync'; +import { KIBANA_ROOT } from '../'; +import elasticsearch from 'elasticsearch'; -export function createTestCluster(options = {}) { +export function createEsTestCluster(options = {}) { const { port = esTestConfig.getPort(), password = 'changeme', license = 'oss', log, - basePath = resolve(__dirname, '../../../.es'), + basePath = resolve(KIBANA_ROOT, '.es'), + // Use source when running on CI + from = esTestConfig.getBuildFrom(), } = options; - const randomHash = Math.random().toString(36).substring(2); + const randomHash = Math.random() + .toString(36) + .substring(2); const clusterName = `test-${randomHash}`; const config = { version: esTestConfig.getVersion(), installPath: resolve(basePath, clusterName), - sourcePath: resolve(__dirname, '../../../../elasticsearch'), + sourcePath: resolve(KIBANA_ROOT, '../elasticsearch'), password, license, basePath, @@ -29,9 +53,6 @@ export function createTestCluster(options = {}) { const cluster = new Cluster(log); - // Use source when running on CI - const from = options.from || esTestConfig.getBuildFrom(); - return new class EsTestCluster { getStartTimeout() { const second = 1000; @@ -51,18 +72,20 @@ export function createTestCluster(options = {}) { `cluster.name=${clusterName}`, `http.port=${port}`, `discovery.zen.ping.unicast.hosts=localhost:${port}`, - ...esArgs + ...esArgs, ], }); } async stop() { await cluster.stop(); + log.info('[es] stopped'); } async cleanup() { await this.stop(); rmrfSync(config.installPath); + log.info('[es] cleanup complete'); } /** @@ -84,7 +107,7 @@ export function createTestCluster(options = {}) { return format(parts); } - }; + }(); } /** diff --git a/packages/kbn-test/src/es/es_test_config.js b/packages/kbn-test/src/es/es_test_config.js new file mode 100644 index 00000000000000..2e9e91e50b4b2b --- /dev/null +++ b/packages/kbn-test/src/es/es_test_config.js @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import url, { format as formatUrl } from 'url'; +import pkg from '../../../../package.json'; +import { adminTestUser } from '../kbn'; + +export const esTestConfig = new class EsTestConfig { + getVersion() { + return process.env.TEST_ES_BRANCH || pkg.version; + } + + getPort() { + return this.getUrlParts().port; + } + + getUrl() { + return formatUrl(this.getUrlParts()); + } + + getBuildFrom() { + return process.env.TEST_ES_FROM || 'snapshot'; + } + + getUrlParts() { + // Allow setting one complete TEST_ES_URL for Es like https://elastic:changeme@myCloudInstance:9200 + if (process.env.TEST_ES_URL) { + const testEsUrl = url.parse(process.env.TEST_ES_URL); + return { + // have to remove the ":" off protocol + protocol: testEsUrl.protocol.slice(0, -1), + hostname: testEsUrl.hostname, + port: parseInt(testEsUrl.port, 10), + username: testEsUrl.auth.split(':')[0], + password: testEsUrl.auth.split(':')[1], + auth: testEsUrl.auth, + }; + } + + const username = process.env.TEST_KIBANA_USERNAME || adminTestUser.username; + const password = process.env.TEST_KIBANA_PASSWORD || adminTestUser.password; + return { + // Allow setting any individual component(s) of the URL, + // or use default values (username and password from ../kbn/users.js) + protocol: process.env.TEST_ES_PROTOCOL || 'http', + hostname: process.env.TEST_ES_HOSTNAME || 'localhost', + port: parseInt(process.env.TEST_ES_PORT, 10) || 9220, + auth: `${username}:${password}`, + username: username, + password: password, + }; + } +}(); diff --git a/packages/kbn-test/src/es/index.js b/packages/kbn-test/src/es/index.js new file mode 100644 index 00000000000000..029f71e5cc283c --- /dev/null +++ b/packages/kbn-test/src/es/index.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { createEsTestCluster } from './es_test_cluster.js'; +export { esTestConfig } from './es_test_config'; diff --git a/packages/kbn-test/src/es/rmrf_sync.js b/packages/kbn-test/src/es/rmrf_sync.js new file mode 100644 index 00000000000000..dafbfb1661479d --- /dev/null +++ b/packages/kbn-test/src/es/rmrf_sync.js @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as fs from 'fs'; + +/** + * Recurive deletion for a directory + * + * @param {String} path + */ +export function rmrfSync(path) { + if (fs.existsSync(path)) { + fs.readdirSync(path).forEach(file => { + const curPath = path + '/' + file; + + if (fs.lstatSync(curPath).isDirectory()) { + rmrfSync(curPath); + } else { + fs.unlinkSync(curPath); + } + }); + fs.rmdirSync(path); + } +} diff --git a/packages/kbn-test/src/functional_tests/cli/index.js b/packages/kbn-test/src/functional_tests/cli/index.js new file mode 100644 index 00000000000000..a423672005950b --- /dev/null +++ b/packages/kbn-test/src/functional_tests/cli/index.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { runTestsCli } from './run_tests_cli'; +export { startServersCli } from './start_servers_cli'; diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests_cli.js b/packages/kbn-test/src/functional_tests/cli/run_tests_cli.js new file mode 100644 index 00000000000000..0f366b6278dfda --- /dev/null +++ b/packages/kbn-test/src/functional_tests/cli/run_tests_cli.js @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import dedent from 'dedent'; +import getopts from 'getopts'; +import { createToolingLog, pickLevelFromFlags } from '@kbn/dev-utils'; +import { runTests } from '../../'; + +/** + * Run servers and tests for each config + * Only cares about --config option. Other options + * are passed directly to functional_test_runner, such as + * --bail, --verbose, etc. + * @param {string[]} defaultConfigPaths Array of paths to configs to use + * if no config option is passed + */ +export async function runTestsCli(defaultConfigPaths) { + const { configs, help, bail, log, installDir } = processArgs( + defaultConfigPaths + ); + + if (help) return displayHelp(); + + if (!configs || configs.length === 0) { + log.error( + `Run Tests requires at least one path to a config. Leave blank to use defaults.` + ); + process.exit(9); + } + + try { + await runTests(configs, { bail, log, installDir }); + } catch (err) { + log.error('FATAL ERROR'); + log.error(err); + process.exit(1); + } +} + +function processArgs(defaultConfigPaths) { + // If no args are passed, use {} + const options = getopts(process.argv.slice(2)) || {}; + + // If --config is passed without paths, it's "true", so use default + const configs = + typeof options.config === 'string' || Array.isArray(options.config) + ? [].concat(options.config) + : defaultConfigPaths; + + const log = createToolingLog(pickLevelFromFlags(options)); + log.pipe(process.stdout); + + return { + configs, + log, + help: options.help, + bail: options.bail, + installDir: options['kibana-install-dir'], + rest: options._, + }; +} + +function displayHelp() { + console.log( + dedent(` + Run Functional Tests + + Usage: node scripts/functional_tests [options] + + --config Option to pass in a config + Can pass in multiple configs with + --config file1 --config file2 --config file3 + --kibana-install-dir + Run Kibana from an existing install directory + Default: run from source + --bail Stop the test run at the first failure + --help Display this menu and exit + + Log level options: + + --verbose + --debug + --quiet Log errors + --silent + `) + ); +} diff --git a/packages/kbn-test/src/functional_tests/cli/start_servers_cli.js b/packages/kbn-test/src/functional_tests/cli/start_servers_cli.js new file mode 100644 index 00000000000000..31266b8e7d0dc9 --- /dev/null +++ b/packages/kbn-test/src/functional_tests/cli/start_servers_cli.js @@ -0,0 +1,99 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import chalk from 'chalk'; +import dedent from 'dedent'; +import getopts from 'getopts'; +import { createToolingLog, pickLevelFromFlags } from '@kbn/dev-utils'; +import { startServers } from '../../'; + +/** + * Start servers + * @param {string} configPath path to config + */ +export async function startServersCli(defaultConfigPath) { + const { config, log, help, installDir } = processArgv(defaultConfigPath); + + if (help) return displayHelp(); + + if (!config) { + log.error( + `Start Servers requires one path to a config. Leave blank to use default.` + ); + process.exit(1); + } + + try { + await startServers(config, { log, installDir }); + } catch (err) { + log.error('FATAL ERROR'); + log.error(err); + process.exit(1); + } +} + +function processArgv(defaultConfigPath) { + const options = getopts(process.argv.slice(2)) || {}; + + if (Array.isArray(options.config)) { + console.log( + chalk.red( + `Starting servers requires a single config path. Multiple were passed.` + ) + ); + process.exit(9); + } + + const config = + typeof options.config === 'string' ? options.config : defaultConfigPath; + + const log = createToolingLog(pickLevelFromFlags(options)); + log.pipe(process.stdout); + + return { + config, + log, + installDir: options.kibanaInstallDir, + help: options.help, + rest: options._, + }; +} + +function displayHelp() { + console.log( + dedent(` + Start Functional Test Servers + + Usage: node scripts/functional_tests_server [options] + + --config Option to pass in a config + --kibana-install-dir + Run Kibana from an existing install directory + Default: run from source + --help Display this menu and exit + + Log level options: + + --verbose + --debug + --quiet Log errors + --silent + `) + ); +} diff --git a/packages/kbn-test/src/functional_tests/lib/auth.js b/packages/kbn-test/src/functional_tests/lib/auth.js new file mode 100644 index 00000000000000..5005bd877f8f94 --- /dev/null +++ b/packages/kbn-test/src/functional_tests/lib/auth.js @@ -0,0 +1,90 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { format as formatUrl } from 'url'; + +import request from 'request'; +import { delay, fromNode as fcb } from 'bluebird'; + +export const DEFAULT_SUPERUSER_PASS = 'iamsuperuser'; + +async function updateCredentials(port, auth, username, password, retries = 10) { + const result = await fcb(cb => + request( + { + method: 'PUT', + uri: formatUrl({ + protocol: 'http:', + auth, + hostname: 'localhost', + port, + pathname: `/_xpack/security/user/${username}/_password`, + }), + json: true, + body: { password }, + }, + (err, httpResponse, body) => { + cb(err, { httpResponse, body }); + } + ) + ); + + const { body, httpResponse } = result; + const { statusCode } = httpResponse; + if (statusCode === 200) { + return; + } + + if (retries > 0) { + await delay(2500); + return await updateCredentials(port, auth, username, password, retries - 1); + } + + throw new Error( + `${statusCode} response, expected 200 -- ${JSON.stringify(body)}` + ); +} + +export async function setupUsers(log, config) { + const esPort = config.get('servers.elasticsearch.port'); + + // track the current credentials for the `elastic` user as + // they will likely change as we apply updates + let auth = `elastic:${DEFAULT_SUPERUSER_PASS}`; + + // list of updates we need to apply + const updates = [ + config.get('servers.elasticsearch'), + config.get('servers.kibana'), + ]; + + for (const { username, password } of updates) { + log.info('setting %j user password to %j', username, password); + await updateCredentials(esPort, auth, username, password); + if (username === 'elastic') { + auth = `elastic:${password}`; + } + } +} diff --git a/packages/kbn-test/src/functional_tests/lib/index.js b/packages/kbn-test/src/functional_tests/lib/index.js new file mode 100644 index 00000000000000..5116dc060f41fa --- /dev/null +++ b/packages/kbn-test/src/functional_tests/lib/index.js @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { runKibanaServer } from './run_kibana_server'; +export { runElasticsearch } from './run_elasticsearch'; +export { runFtr } from './run_ftr'; +export { + KIBANA_ROOT, + KIBANA_FTR_SCRIPT, + FUNCTIONAL_CONFIG_PATH, + API_CONFIG_PATH, +} from './paths'; diff --git a/packages/kbn-test/src/functional_tests/lib/paths.js b/packages/kbn-test/src/functional_tests/lib/paths.js new file mode 100644 index 00000000000000..0aae3c46281298 --- /dev/null +++ b/packages/kbn-test/src/functional_tests/lib/paths.js @@ -0,0 +1,44 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve, relative } from 'path'; + +// resolve() treats relative paths as relative to process.cwd(), +// so to return a relative path we use relative() +function resolveRelative(path) { + return relative(process.cwd(), resolve(path)); +} + +export const KIBANA_EXEC = 'node'; +export const KIBANA_EXEC_PATH = resolveRelative('scripts/kibana'); +export const KIBANA_ROOT = resolve(__dirname, '../../../../../'); +export const KIBANA_FTR_SCRIPT = resolve( + KIBANA_ROOT, + 'scripts/functional_test_runner' +); +export const PROJECT_ROOT = resolve(__dirname, '../../../../../../'); +export const FUNCTIONAL_CONFIG_PATH = resolve( + KIBANA_ROOT, + 'test/functional/config' +); +export const API_CONFIG_PATH = resolve( + KIBANA_ROOT, + 'test/api_integration/config' +); +export const OPTIMIZE_BUNDLE_DIR = resolve(KIBANA_ROOT, 'optimize/bundles'); diff --git a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js new file mode 100644 index 00000000000000..35b6d862a299c9 --- /dev/null +++ b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.js @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve } from 'path'; +import { KIBANA_ROOT } from './paths'; +import { createEsTestCluster } from '../../es'; + +import { setupUsers, DEFAULT_SUPERUSER_PASS } from './auth'; + +export async function runElasticsearch({ config, log }) { + const isOss = config.get('esTestCluster.license') === 'oss'; + + const cluster = createEsTestCluster({ + port: config.get('servers.elasticsearch.port'), + password: !isOss + ? DEFAULT_SUPERUSER_PASS + : config.get('servers.elasticsearch.password'), + license: config.get('esTestCluster.license'), + log, + basePath: resolve(KIBANA_ROOT, '.es'), + from: config.get('esTestCluster.from'), + }); + + const esArgs = config.get('esTestCluster.serverArgs'); + + await cluster.start(esArgs); + + if (!isOss) { + await setupUsers(log, config); + } + + return cluster; +} diff --git a/packages/kbn-test/src/functional_tests/lib/run_ftr.js b/packages/kbn-test/src/functional_tests/lib/run_ftr.js new file mode 100644 index 00000000000000..968ec3e1f678df --- /dev/null +++ b/packages/kbn-test/src/functional_tests/lib/run_ftr.js @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { KIBANA_FTR_SCRIPT, PROJECT_ROOT } from './paths'; + +export async function runFtr({ + procs, + configPath, + bail, + log, + cwd = PROJECT_ROOT, +}) { + const args = [KIBANA_FTR_SCRIPT]; + + if (getLogFlag(log)) args.push(`--${getLogFlag(log)}`); + if (bail) args.push('--bail'); + if (configPath) args.push('--config', configPath); + + await procs.run('ftr', { + cmd: 'node', + args, + cwd, + wait: true, + }); +} + +function getLogFlag(log) { + const level = log.getLevel(); + + if (level === 'info') return null; + return level === 'error' ? 'quiet' : level; +} diff --git a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js new file mode 100644 index 00000000000000..ae92fe9e34c97d --- /dev/null +++ b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.js @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve } from 'path'; +import { KIBANA_ROOT, KIBANA_EXEC, KIBANA_EXEC_PATH } from './paths'; + +export async function runKibanaServer({ procs, config, options }) { + const { installDir } = options; + + await procs.run('kibana', { + cmd: getKibanaCmd(installDir), + args: getCliArgs(config, options), + env: { + FORCE_COLOR: 1, + ...process.env, + }, + cwd: installDir || KIBANA_ROOT, + wait: /Server running/, + }); +} + +function getKibanaCmd(installDir) { + if (installDir) { + return process.platform.startsWith('win') + ? resolve(installDir, 'bin/kibana.bat') + : resolve(installDir, 'bin/kibana'); + } + + return KIBANA_EXEC; +} + +function getCliArgs(config, { devMode, installDir }) { + const buildArgs = config.get('kbnTestServer.buildArgs') || []; + const sourceArgs = config.get('kbnTestServer.sourceArgs') || []; + const serverArgs = config.get('kbnTestServer.serverArgs') || []; + + if (devMode) serverArgs.push('--dev'); + + return installDir + ? [...serverArgs, ...buildArgs] + : [KIBANA_EXEC_PATH, ...serverArgs, ...sourceArgs]; +} diff --git a/packages/kbn-test/src/functional_tests/tasks.js b/packages/kbn-test/src/functional_tests/tasks.js new file mode 100644 index 00000000000000..6c4ceaf4891e49 --- /dev/null +++ b/packages/kbn-test/src/functional_tests/tasks.js @@ -0,0 +1,122 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { relative, resolve } from 'path'; +import Rx from 'rxjs/Rx'; +import { withProcRunner } from '@kbn/dev-utils'; + +import { + runElasticsearch, + runKibanaServer, + runFtr, + KIBANA_FTR_SCRIPT, +} from './lib'; + +import { readConfigFile } from '../../../../src/functional_test_runner/lib'; + +const SUCCESS_MESSAGE = ` + +Elasticsearch and Kibana are ready for functional testing. Start the functional tests +in another terminal session by running this command from this directory: + + node ${relative(process.cwd(), KIBANA_FTR_SCRIPT)} + +`; + +/** + * Run servers and tests for each config + * @param {string[]} configPaths Array of paths to configs + * @param {object} options Optional + * @param {Log} options.log Optional logger + * @param {string} options.installDir Optional installation dir + * from which to run Kibana + * @param {boolean} options.bail Whether to exit test run at the first failure + */ +export async function runTests(configPaths, options) { + for (const configPath of configPaths) { + await runSingleConfig(resolve(process.cwd(), configPath), options); + } +} + +/** + * Start only servers using single config + * @param {string} configPath Path to a config file + * @param {object} options Optional + * @param {Log} options.log Optional logger + * @param {string} options.installDir Optional installation dir + * from which to run Kibana + */ +export async function startServers(configPath, options) { + const { log } = options; + configPath = resolve(process.cwd(), configPath); + + await withProcRunner(log, async procs => { + const config = await readConfigFile(log, configPath); + + const es = await runElasticsearch({ config, log }); + await runKibanaServer({ + procs, + config, + options: { ...options, devMode: true }, + }); + + // wait for 5 seconds of silence before logging the + // success message so that it doesn't get buried + await silence(5000, { log }); + log.info(SUCCESS_MESSAGE); + + await procs.waitForAllToStop(); + await es.cleanup(); + }); +} + +async function silence(milliseconds, { log }) { + await Rx.Observable.fromEvent(log, 'data') + .startWith(null) + .switchMap(() => Rx.Observable.timer(milliseconds)) + .take(1) + .toPromise(); +} + +/* + * Start servers and run tests for single config + */ +async function runSingleConfig(configPath, options) { + const { bail, log } = options; + + await withProcRunner(log, async procs => { + const config = await readConfigFile(log, configPath); + + const es = await runElasticsearch({ config, log }); + await runKibanaServer({ procs, config, options }); + + // Note: When solving how to incorporate functional_test_runner + // clean this up + await runFtr({ + procs, + configPath, + bail, + log, + cwd: process.cwd(), + }); + + await procs.stop('kibana'); + await es.cleanup(); + }); +} diff --git a/packages/kbn-test/src/index.js b/packages/kbn-test/src/index.js new file mode 100644 index 00000000000000..7cacee4e4dd714 --- /dev/null +++ b/packages/kbn-test/src/index.js @@ -0,0 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { runTestsCli, startServersCli } from './functional_tests/cli'; + +export { runTests, startServers } from './functional_tests/tasks'; + +export { OPTIMIZE_BUNDLE_DIR, KIBANA_ROOT } from './functional_tests/lib/paths'; + +export { esTestConfig, createEsTestCluster } from './es'; + +export { + kbnTestConfig, + kibanaServerTestUser, + kibanaTestUser, + adminTestUser, +} from './kbn'; diff --git a/packages/kbn-test/src/kbn/index.js b/packages/kbn-test/src/kbn/index.js new file mode 100644 index 00000000000000..4ce3d06d3c8fcb --- /dev/null +++ b/packages/kbn-test/src/kbn/index.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { kbnTestConfig } from './kbn_test_config'; +export { kibanaTestUser, kibanaServerTestUser, adminTestUser } from './users'; diff --git a/packages/kbn-test/src/kbn/kbn_test_config.js b/packages/kbn-test/src/kbn/kbn_test_config.js new file mode 100644 index 00000000000000..24e4edcbf9f088 --- /dev/null +++ b/packages/kbn-test/src/kbn/kbn_test_config.js @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { kibanaTestUser } from './users'; +import url from 'url'; + +export const kbnTestConfig = new class KbnTestConfig { + getPort() { + return this.getUrlParts().port; + } + + getUrlParts() { + // allow setting one complete TEST_KIBANA_URL for ES like https://elastic:changeme@example.com:9200 + if (process.env.TEST_KIBANA_URL) { + const testKibanaUrl = url.parse(process.env.TEST_KIBANA_URL); + return { + protocol: testKibanaUrl.protocol.slice(0, -1), + hostname: testKibanaUrl.hostname, + port: parseInt(testKibanaUrl.port, 10), + auth: testKibanaUrl.auth, + username: testKibanaUrl.auth.split(':')[0], + password: testKibanaUrl.auth.split(':')[1], + }; + } + + const username = + process.env.TEST_KIBANA_USERNAME || kibanaTestUser.username; + const password = + process.env.TEST_KIBANA_PASSWORD || kibanaTestUser.password; + return { + protocol: process.env.TEST_KIBANA_PROTOCOL || 'http', + hostname: process.env.TEST_KIBANA_HOSTNAME || 'localhost', + port: parseInt(process.env.TEST_KIBANA_PORT, 10) || 5620, + auth: `${username}:${password}`, + username, + password, + }; + } +}(); diff --git a/packages/kbn-test/src/kbn/users.js b/packages/kbn-test/src/kbn/users.js new file mode 100644 index 00000000000000..1d4a903d60cfa2 --- /dev/null +++ b/packages/kbn-test/src/kbn/users.js @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const env = process.env; + +export const kibanaTestUser = { + username: env.TEST_KIBANA_USER || 'elastic', + password: env.TEST_KIBANA_PASS || 'changeme', +}; + +export const kibanaServerTestUser = { + username: env.TEST_KIBANA_SERVER_USER || 'kibana', + password: env.TEST_KIBANA_SERVER_PASS || 'changeme', +}; + +export const adminTestUser = { + username: env.TEST_ES_USER || 'elastic', + password: env.TEST_ES_PASS || 'changeme', +}; diff --git a/packages/kbn-test/yarn.lock b/packages/kbn-test/yarn.lock new file mode 100644 index 00000000000000..4cef430f3ffd67 --- /dev/null +++ b/packages/kbn-test/yarn.lock @@ -0,0 +1,1685 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@kbn/babel-preset@link:../kbn-babel-preset": + version "0.0.0" + uid "" + +"@kbn/dev-utils@link:../kbn-dev-utils": + version "0.0.0" + uid "" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + dependencies: + micromatch "^2.1.5" + normalize-path "^2.0.0" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +are-we-there-yet@~1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + +babel-cli@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.26.0.tgz#502ab54874d7db88ad00b887a06383ce03d002f1" + dependencies: + babel-core "^6.26.0" + babel-polyfill "^6.26.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + commander "^2.11.0" + convert-source-map "^1.5.0" + fs-readdir-recursive "^1.0.0" + glob "^7.1.2" + lodash "^4.17.4" + output-file-sync "^1.1.2" + path-is-absolute "^1.0.1" + slash "^1.0.0" + source-map "^0.5.6" + v8flags "^2.1.1" + optionalDependencies: + chokidar "^1.6.1" + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-builder-react-jsx@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + esutils "^2.0.2" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-add-module-exports@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-async-generators@^6.5.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" + +babel-plugin-syntax-class-properties@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-flow@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" + +babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + +babel-plugin-syntax-object-rest-spread@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-generator-functions@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-generators "^6.5.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-class-properties@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" + dependencies: + babel-helper-function-name "^6.24.1" + babel-plugin-syntax-class-properties "^6.8.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-define@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-define/-/babel-plugin-transform-define-1.3.0.tgz#94c5f9459c810c738cc7c50cbd44a31829d6f319" + dependencies: + lodash "4.17.4" + traverse "0.6.6" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-flow-strip-types@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" + dependencies: + babel-plugin-syntax-flow "^6.18.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-object-rest-spread@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-runtime "^6.26.0" + +babel-plugin-transform-react-display-name@^6.23.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-self@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-source@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" + dependencies: + babel-helper-builder-react-jsx "^6.24.1" + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-polyfill@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" + dependencies: + babel-runtime "^6.26.0" + core-js "^2.5.0" + regenerator-runtime "^0.10.5" + +babel-preset-env@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.4.0.tgz#c8e02a3bcc7792f23cded68e0355b9d4c28f0f7a" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^1.4.0" + invariant "^2.2.2" + +babel-preset-flow@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" + dependencies: + babel-plugin-transform-flow-strip-types "^6.22.0" + +babel-preset-react@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" + dependencies: + babel-plugin-syntax-jsx "^6.3.13" + babel-plugin-transform-react-display-name "^6.23.0" + babel-plugin-transform-react-jsx "^6.24.1" + babel-plugin-transform-react-jsx-self "^6.22.0" + babel-plugin-transform-react-jsx-source "^6.22.0" + babel-preset-flow "^6.23.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +binary-extensions@^1.0.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" + +bl@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +browserslist@^1.4.0: + version "1.7.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" + dependencies: + caniuse-db "^1.0.30000639" + electron-to-chromium "^1.2.7" + +buffer-alloc-unsafe@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz#ffe1f67551dd055737de253337bfe853dfab1a6a" + +buffer-alloc@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.1.0.tgz#05514d33bf1656d3540c684f65b1202e90eca303" + dependencies: + buffer-alloc-unsafe "^0.1.0" + buffer-fill "^0.1.0" + +buffer-fill@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-0.1.1.tgz#76d825c4d6e50e06b7a31eb520c04d08cc235071" + +caniuse-db@^1.0.30000639: + version "1.0.30000836" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000836.tgz#788b6c8f6f02991743b18cdbbd54f96d05b4b95a" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.3.0, chalk@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chokidar@^1.6.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +chownr@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +commander@^2.11.0: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +convert-source-map@^1.5.0, convert-source-map@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +core-js@^2.4.0, core-js@^2.5.0: + version "2.5.6" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.6.tgz#0fe6d45bf3cac3ac364a9d72de7576f4eb221b9d" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +debug@^2.1.2, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + +deep-extend@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + +electron-to-chromium@^1.2.7: + version "1.3.45" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.45.tgz#458ac1b1c5c760ce8811a16d2bfbd97ec30bafb8" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + dependencies: + once "^1.4.0" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +execa@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" + dependencies: + cross-spawn "^6.0.0" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +fill-range@^2.1.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^3.0.0" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + dependencies: + minipass "^2.2.1" + +fs-readdir-recursive@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.3.tgz#08292982e7059f6674c93d8b829c1e8604979ac0" + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.9.0" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +getopts@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.0.6.tgz#4788d533a977527e79efd57b5e742ffa0dd33105" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@^7.0.5, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +graceful-fs@^4.1.2, graceful-fs@^4.1.4: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +iconv-lite@^0.4.4: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + dependencies: + loose-envify "^1.0.0" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + +lodash@4.17.4: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lodash@^4.17.4: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + +loose-envify@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + +math-random@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" + +micromatch@^2.1.5: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minipass@^2.2.1, minipass@^2.2.4: + version "2.3.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.0.tgz#2e11b1c46df7fe7f1afbe9a490280add21ffe384" + dependencies: + safe-buffer "^5.1.1" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + +mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +moment@^2.20.1: + version "2.22.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.1.tgz#529a2e9bf973f259c9643d237fda84de3a26e8ad" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +needle@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + +nice-try@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" + +node-pre-gyp@^0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.9.1.tgz#f11c07516dd92f87199dbc7e1838eab7cd56c9e0" + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.0" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.1.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-path@^2.0.0, normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + +npm-packlist@^1.1.6: + version "1.1.10" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +output-file-sync@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76" + dependencies: + graceful-fs "^4.1.4" + mkdirp "^0.5.1" + object-assign "^4.1.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +pump@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +randomatic@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.0.0.tgz#d35490030eb4f7578de292ce6dfb04a91a128923" + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + +rc@^1.1.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.7.tgz#8a10ca30d588d00464360372b890d06dacd02297" + dependencies: + deep-extend "^0.5.1" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + +regenerate@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" + +regenerator-runtime@^0.10.5: + version "0.10.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +rimraf@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +rxjs@^5.4.3: + version "5.5.10" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.10.tgz#fde02d7a614f6c8683d0d1957827f492e09db045" + dependencies: + symbol-observable "1.0.1" + +safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + +semver@^5.3.0, semver@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + +source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^5.3.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + +symbol-observable@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" + +tar-fs@^1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.2.tgz#17e5239747e399f7e77344f5f53365f04af53577" + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-stream@^1.1.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.0.tgz#a50efaa7b17760b82c27b3cae4a301a8254a5715" + dependencies: + bl "^1.0.0" + buffer-alloc "^1.1.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.0.0" + to-buffer "^1.1.0" + xtend "^4.0.0" + +tar@^4: + version "4.4.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.2.tgz#60685211ba46b38847b1ae7ee1a24d744a2cd462" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.2.4" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + dependencies: + os-tmpdir "~1.0.2" + +to-buffer@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +traverse@0.6.6: + version "0.6.6" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" + +tree-kill@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +user-home@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +v8flags@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" + dependencies: + user-home "^1.1.1" + +which@^1.2.9: + version "1.3.0" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + dependencies: + string-width "^1.0.2" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + +zlib@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/zlib/-/zlib-1.0.5.tgz#6e7c972fc371c645a6afb03ab14769def114fcc0" diff --git a/packages/kbn-ui-framework/Gruntfile.js b/packages/kbn-ui-framework/Gruntfile.js index 992d0b5f9b2570..3012426bb31847 100644 --- a/packages/kbn-ui-framework/Gruntfile.js +++ b/packages/kbn-ui-framework/Gruntfile.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const sass = require('node-sass'); const postcss = require('postcss'); const postcssConfig = require('../../src/optimize/postcss.config'); @@ -36,7 +55,7 @@ module.exports = function (grunt) { dest: '.', options: { presets: [ - require.resolve('@kbn/babel-preset/webpack') + require.resolve('@kbn/babel-preset/webpack_preset') ] }, } diff --git a/packages/kbn-ui-framework/components/index.js b/packages/kbn-ui-framework/components/index.js index aa94edb4a57f04..bcd5bd6f65cdfc 100644 --- a/packages/kbn-ui-framework/components/index.js +++ b/packages/kbn-ui-framework/components/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export * from '../src/components'; diff --git a/packages/kbn-ui-framework/doc_site/postcss.config.js b/packages/kbn-ui-framework/doc_site/postcss.config.js index dc06a629c48b74..62a7f705ba7580 100644 --- a/packages/kbn-ui-framework/doc_site/postcss.config.js +++ b/packages/kbn-ui-framework/doc_site/postcss.config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = { plugins: [ require('autoprefixer')({ browsers: ['last 2 versions'] }) diff --git a/packages/kbn-ui-framework/doc_site/src/actions/action_types.js b/packages/kbn-ui-framework/doc_site/src/actions/action_types.js index 66ef2b2afcd5f4..2b9cb751c3517e 100644 --- a/packages/kbn-ui-framework/doc_site/src/actions/action_types.js +++ b/packages/kbn-ui-framework/doc_site/src/actions/action_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import keyMirror from 'keymirror'; diff --git a/packages/kbn-ui-framework/doc_site/src/actions/code_viewer_actions.js b/packages/kbn-ui-framework/doc_site/src/actions/code_viewer_actions.js index b193af7f5eb3da..17c1cdcadab600 100644 --- a/packages/kbn-ui-framework/doc_site/src/actions/code_viewer_actions.js +++ b/packages/kbn-ui-framework/doc_site/src/actions/code_viewer_actions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ActionTypes from './action_types'; export const openCodeViewer = (source, title) => ({ diff --git a/packages/kbn-ui-framework/doc_site/src/actions/example_nav_actions.js b/packages/kbn-ui-framework/doc_site/src/actions/example_nav_actions.js index cbcc5c542403f8..205be7920aa60e 100644 --- a/packages/kbn-ui-framework/doc_site/src/actions/example_nav_actions.js +++ b/packages/kbn-ui-framework/doc_site/src/actions/example_nav_actions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ActionTypes from './action_types'; export const registerSection = (id, name) => ({ diff --git a/packages/kbn-ui-framework/doc_site/src/actions/index.js b/packages/kbn-ui-framework/doc_site/src/actions/index.js index 9517d850e4a2bb..3658958e9c6c34 100644 --- a/packages/kbn-ui-framework/doc_site/src/actions/index.js +++ b/packages/kbn-ui-framework/doc_site/src/actions/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { openCodeViewer, closeCodeViewer, diff --git a/packages/kbn-ui-framework/doc_site/src/actions/sandbox_actions.js b/packages/kbn-ui-framework/doc_site/src/actions/sandbox_actions.js index 33b7e345f717df..2bf5dd79aee07a 100644 --- a/packages/kbn-ui-framework/doc_site/src/actions/sandbox_actions.js +++ b/packages/kbn-ui-framework/doc_site/src/actions/sandbox_actions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ActionTypes from './action_types'; export const openSandbox = () => ({ diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_code/guide_code.js b/packages/kbn-ui-framework/doc_site/src/components/guide_code/guide_code.js index 8bca4d55222be8..d496e05514c1aa 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_code/guide_code.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_code/guide_code.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; export const GuideCode = props => ( diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_code_viewer/guide_code_viewer.js b/packages/kbn-ui-framework/doc_site/src/components/guide_code_viewer/guide_code_viewer.js index ed47a17bcb31b4..68b8c8f810e1e4 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_code_viewer/guide_code_viewer.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_code_viewer/guide_code_viewer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_demo/guide_demo.js b/packages/kbn-ui-framework/doc_site/src/components/guide_demo/guide_demo.js index 5e88de189b845e..42da5ad172cf65 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_demo/guide_demo.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_demo/guide_demo.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_link/guide_link.js b/packages/kbn-ui-framework/doc_site/src/components/guide_link/guide_link.js index d925456a68413a..a24fd96121873c 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_link/guide_link.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_link/guide_link.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; export const GuideLink = props => ( diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_nav/guide_nav.js b/packages/kbn-ui-framework/doc_site/src/components/guide_nav/guide_nav.js index 55427014a4e229..cee256da795133 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_nav/guide_nav.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_nav/guide_nav.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page.js b/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page.js index 7407c3204eaa2d..83560fa2c98bc0 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page_container.js b/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page_container.js index 70c9b68e55cc11..5d8e6993abe4e8 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page_container.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_page/guide_page_container.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { connect } from 'react-redux'; import { getSections } from '../../store'; import { GuidePage } from './guide_page'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js b/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js index 22430cb8fa6f4e..96be2d83dcfbc9 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav_item.js b/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav_item.js index 4bf95d1593b015..3d5497e6c8f4f4 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav_item.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_page_side_nav/guide_page_side_nav_item.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox.js b/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox.js index ec9501f6c55632..6d4c9cddae0be3 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle.js b/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle.js index 81ed902c2373a8..fdec7904121322 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle_container.js b/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle_container.js index ec0f2ee3781520..fee8e5e770e8b2 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle_container.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_sandbox/guide_sandbox_code_toggle_container.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { connect } from 'react-redux'; import { GuideSandboxCodeToggle } from './guide_sandbox_code_toggle'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section.js b/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section.js index 2680cbfc4e7d46..99a68e95751144 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section_container.js b/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section_container.js index 08abaef4dbe6fd..0ee6f01f3917dc 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section_container.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section_container.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { connect } from 'react-redux'; import { GuideSection } from './guide_section'; diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section_types.js b/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section_types.js index efb35d56547059..9df404fad572fe 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section_types.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_section/guide_section_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const GuideSectionTypes = { JS: 'JavaScript', HTML: 'HTML', diff --git a/packages/kbn-ui-framework/doc_site/src/components/guide_text/guide_text.js b/packages/kbn-ui-framework/doc_site/src/components/guide_text/guide_text.js index 0a87e624621b67..2cbc99aa122202 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/guide_text/guide_text.js +++ b/packages/kbn-ui-framework/doc_site/src/components/guide_text/guide_text.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; export const GuideText = props => ( diff --git a/packages/kbn-ui-framework/doc_site/src/components/index.js b/packages/kbn-ui-framework/doc_site/src/components/index.js index 71f3cd1bdc3e3b..45963064d6d434 100644 --- a/packages/kbn-ui-framework/doc_site/src/components/index.js +++ b/packages/kbn-ui-framework/doc_site/src/components/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { GuideCode } from './guide_code/guide_code'; export { GuideCodeViewer } from './guide_code_viewer/guide_code_viewer'; export { GuideDemo } from './guide_demo/guide_demo'; diff --git a/packages/kbn-ui-framework/doc_site/src/index.js b/packages/kbn-ui-framework/doc_site/src/index.js index dfce863493f228..094437d85e6b64 100644 --- a/packages/kbn-ui-framework/doc_site/src/index.js +++ b/packages/kbn-ui-framework/doc_site/src/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('./main.scss'); import 'babel-polyfill'; diff --git a/packages/kbn-ui-framework/doc_site/src/services/example/create_example.js b/packages/kbn-ui-framework/doc_site/src/services/example/create_example.js index e42ba1362db01e..8b8953e1421b03 100644 --- a/packages/kbn-ui-framework/doc_site/src/services/example/create_example.js +++ b/packages/kbn-ui-framework/doc_site/src/services/example/create_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* eslint import/named: 0 */ import { GuideExample, diff --git a/packages/kbn-ui-framework/doc_site/src/services/index.js b/packages/kbn-ui-framework/doc_site/src/services/index.js index eaf038ac297277..a53cde2d549227 100644 --- a/packages/kbn-ui-framework/doc_site/src/services/index.js +++ b/packages/kbn-ui-framework/doc_site/src/services/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { renderToHtml } from './string/render_to_html'; export { default as createExample } from './example/create_example'; diff --git a/packages/kbn-ui-framework/doc_site/src/services/js_injector/js_injector.js b/packages/kbn-ui-framework/doc_site/src/services/js_injector/js_injector.js index f77986272390cf..14131ba7967a7e 100644 --- a/packages/kbn-ui-framework/doc_site/src/services/js_injector/js_injector.js +++ b/packages/kbn-ui-framework/doc_site/src/services/js_injector/js_injector.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; diff --git a/packages/kbn-ui-framework/doc_site/src/services/routes/routes.js b/packages/kbn-ui-framework/doc_site/src/services/routes/routes.js index 072d43e56b54dc..06085fe7bf1dba 100644 --- a/packages/kbn-ui-framework/doc_site/src/services/routes/routes.js +++ b/packages/kbn-ui-framework/doc_site/src/services/routes/routes.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Slugify from '../string/slugify'; import AccessibilityExample diff --git a/packages/kbn-ui-framework/doc_site/src/services/string/render_to_html.js b/packages/kbn-ui-framework/doc_site/src/services/string/render_to_html.js index 1cd47b401c0ac7..7689277715d295 100644 --- a/packages/kbn-ui-framework/doc_site/src/services/string/render_to_html.js +++ b/packages/kbn-ui-framework/doc_site/src/services/string/render_to_html.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/services/string/slugify.js b/packages/kbn-ui-framework/doc_site/src/services/string/slugify.js index 5447929d4bb0a8..8496d36873a64a 100644 --- a/packages/kbn-ui-framework/doc_site/src/services/string/slugify.js +++ b/packages/kbn-ui-framework/doc_site/src/services/string/slugify.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** diff --git a/packages/kbn-ui-framework/doc_site/src/store/configure_store.js b/packages/kbn-ui-framework/doc_site/src/store/configure_store.js index b7160220345bf9..2d6a1b31b0d191 100644 --- a/packages/kbn-ui-framework/doc_site/src/store/configure_store.js +++ b/packages/kbn-ui-framework/doc_site/src/store/configure_store.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { applyMiddleware, createStore, diff --git a/packages/kbn-ui-framework/doc_site/src/store/index.js b/packages/kbn-ui-framework/doc_site/src/store/index.js index 12be83f4b23745..511143e529c6cd 100644 --- a/packages/kbn-ui-framework/doc_site/src/store/index.js +++ b/packages/kbn-ui-framework/doc_site/src/store/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function getIsCodeViewerOpen(state) { return state.codeViewer.isOpen; } diff --git a/packages/kbn-ui-framework/doc_site/src/store/reducers/code_viewer_reducer.js b/packages/kbn-ui-framework/doc_site/src/store/reducers/code_viewer_reducer.js index 5b1ec213371b36..71b15a159d3473 100644 --- a/packages/kbn-ui-framework/doc_site/src/store/reducers/code_viewer_reducer.js +++ b/packages/kbn-ui-framework/doc_site/src/store/reducers/code_viewer_reducer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { LOCATION_CHANGE } from 'react-router-redux'; import ActionTypes from '../../actions/action_types'; diff --git a/packages/kbn-ui-framework/doc_site/src/store/reducers/sandbox_reducer.js b/packages/kbn-ui-framework/doc_site/src/store/reducers/sandbox_reducer.js index aef176e20d1bc4..d03dd40f30f2f4 100644 --- a/packages/kbn-ui-framework/doc_site/src/store/reducers/sandbox_reducer.js +++ b/packages/kbn-ui-framework/doc_site/src/store/reducers/sandbox_reducer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ActionTypes from '../../actions/action_types'; const defaultState = { diff --git a/packages/kbn-ui-framework/doc_site/src/store/reducers/sections_reducer.js b/packages/kbn-ui-framework/doc_site/src/store/reducers/sections_reducer.js index ca4273689bfcfc..6b61c009c51862 100644 --- a/packages/kbn-ui-framework/doc_site/src/store/reducers/sections_reducer.js +++ b/packages/kbn-ui-framework/doc_site/src/store/reducers/sections_reducer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ActionTypes from '../../actions/action_types'; const defaultState = { diff --git a/packages/kbn-ui-framework/doc_site/src/views/accessibility/accessibility_example.js b/packages/kbn-ui-framework/doc_site/src/views/accessibility/accessibility_example.js index 36d446ca32dd07..6fa7333c9079f7 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/accessibility/accessibility_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/accessibility/accessibility_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/accessibility/keyboard_accessible.js b/packages/kbn-ui-framework/doc_site/src/views/accessibility/keyboard_accessible.js index 10241c1c3bd708..c10d7b098033d3 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/accessibility/keyboard_accessible.js +++ b/packages/kbn-ui-framework/doc_site/src/views/accessibility/keyboard_accessible.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/accessibility/screen_reader.js b/packages/kbn-ui-framework/doc_site/src/views/accessibility/screen_reader.js index 49ac86d04cb091..7c7867944c4d3f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/accessibility/screen_reader.js +++ b/packages/kbn-ui-framework/doc_site/src/views/accessibility/screen_reader.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/action_item/action_item.js b/packages/kbn-ui-framework/doc_site/src/views/action_item/action_item.js index 0d61a1b176037e..1568970e32745f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/action_item/action_item.js +++ b/packages/kbn-ui-framework/doc_site/src/views/action_item/action_item.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/action_item/action_item_example.js b/packages/kbn-ui-framework/doc_site/src/views/action_item/action_item_example.js index a45f8861370325..0646ace4549b08 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/action_item/action_item_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/action_item/action_item_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/action_item/action_items_in_menu.js b/packages/kbn-ui-framework/doc_site/src/views/action_item/action_items_in_menu.js index 9391e1198736a9..d253ca84fbf84d 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/action_item/action_items_in_menu.js +++ b/packages/kbn-ui-framework/doc_site/src/views/action_item/action_items_in_menu.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/app_container.js b/packages/kbn-ui-framework/doc_site/src/views/app_container.js index e54a3412302b1a..8af92eb3d72827 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/app_container.js +++ b/packages/kbn-ui-framework/doc_site/src/views/app_container.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/app_view.js b/packages/kbn-ui-framework/doc_site/src/views/app_view.js index 571af1f53a5d51..7a9d7a01b820a0 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/app_view.js +++ b/packages/kbn-ui-framework/doc_site/src/views/app_view.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/badge/badge_example.js b/packages/kbn-ui-framework/doc_site/src/views/badge/badge_example.js index 6b1ebe689233d1..33b228f1713e68 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/badge/badge_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/badge/badge_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/bar/bar.js b/packages/kbn-ui-framework/doc_site/src/views/bar/bar.js index cf01478cb2edee..8c8a7ec94f443d 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/bar/bar.js +++ b/packages/kbn-ui-framework/doc_site/src/views/bar/bar.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/bar/bar_example.js b/packages/kbn-ui-framework/doc_site/src/views/bar/bar_example.js index bb7a709c4cf2b2..a55b4b675e32bd 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/bar/bar_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/bar/bar_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/bar/bar_one_section.js b/packages/kbn-ui-framework/doc_site/src/views/bar/bar_one_section.js index da4ad4bc94d4d5..06962b217592a6 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/bar/bar_one_section.js +++ b/packages/kbn-ui-framework/doc_site/src/views/bar/bar_one_section.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/bar/bar_three_sections.js b/packages/kbn-ui-framework/doc_site/src/views/bar/bar_three_sections.js index c760c08cb029d1..cfaef7df6cfa9a 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/bar/bar_three_sections.js +++ b/packages/kbn-ui-framework/doc_site/src/views/bar/bar_three_sections.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_basic.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_basic.js index 73e8885556abcb..2f7fa6a504beb2 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_basic.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_basic.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_danger.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_danger.js index c8cc212f9579a1..53a66fdc05bae0 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_danger.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_danger.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_elements.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_elements.js index 5a9494ed9aa352..2b2e012421f222 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_elements.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_elements.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_example.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_example.js index ec8e5464b09714..ed633e034acb14 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_group.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_group.js index 2d93f95e340695..bc3c26d67d097e 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_group.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_group.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_group_united.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_group_united.js index 9c833b56391f21..f11e5d8a4f7726 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_group_united.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_group_united.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_hollow.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_hollow.js index 2ca5b3ad8a144a..151a7006a3c2b1 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_hollow.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_hollow.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_loading.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_loading.js index 8404fe5dc5106a..11bb38ce236bd5 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_loading.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_loading.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_primary.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_primary.js index ce40797d3542d4..33e0d4dbf4731f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_primary.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_primary.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_secondary.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_secondary.js index 7ec603cc6fff24..86a38fe5b6c79a 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_secondary.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_secondary.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_warning.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_warning.js index 6fcb718422ace7..edefd1f79524f3 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_warning.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_warning.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/button/button_with_icon.js b/packages/kbn-ui-framework/doc_site/src/views/button/button_with_icon.js index 53aee7a97a83ca..fd2eed744beccb 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/button/button_with_icon.js +++ b/packages/kbn-ui-framework/doc_site/src/views/button/button_with_icon.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/card/card.js b/packages/kbn-ui-framework/doc_site/src/views/card/card.js index 054452ae006aea..88b49d208280c3 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/card/card.js +++ b/packages/kbn-ui-framework/doc_site/src/views/card/card.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/card/card_example.js b/packages/kbn-ui-framework/doc_site/src/views/card/card_example.js index ae8ac815194a5b..1783f24f8af1a1 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/card/card_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/card/card_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/card/card_group.js b/packages/kbn-ui-framework/doc_site/src/views/card/card_group.js index 0b480d2f833981..1f905d54022743 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/card/card_group.js +++ b/packages/kbn-ui-framework/doc_site/src/views/card/card_group.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/code_editor/code_editor.js b/packages/kbn-ui-framework/doc_site/src/views/code_editor/code_editor.js index 7255191438a294..33991dddfbad5b 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/code_editor/code_editor.js +++ b/packages/kbn-ui-framework/doc_site/src/views/code_editor/code_editor.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component } from 'react'; import 'brace/mode/less'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/code_editor/code_editor_example.js b/packages/kbn-ui-framework/doc_site/src/views/code_editor/code_editor_example.js index e8af21a45ceb45..a491bfa8cf22b9 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/code_editor/code_editor_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/code_editor/code_editor_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/code_editor/read_only.js b/packages/kbn-ui-framework/doc_site/src/views/code_editor/read_only.js index 5c455e5e89a60c..7283023f304adf 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/code_editor/read_only.js +++ b/packages/kbn-ui-framework/doc_site/src/views/code_editor/read_only.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component } from 'react'; import 'brace/mode/less'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button.js b/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button.js index 298c47d3b2b8c8..6b12e62913c965 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button.js +++ b/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_aria.js b/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_aria.js index d0ec113a98e286..5be948a319f771 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_aria.js +++ b/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_aria.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component } from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_example.js b/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_example.js index 1898b3987879c4..091600468c1704 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/collapse_button/collapse_button_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker.js b/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker.js index c1582a8d6a44a3..734a229ecbe5f1 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker.js +++ b/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { KuiColorPicker } from '../../../../components'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_clear.js b/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_clear.js index 3d9414f67339e1..188e50a007ccb4 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_clear.js +++ b/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_clear.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_example.js b/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_example.js index 7ba4cabd6ca588..ec5498a432df41 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_no_color_label.js b/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_no_color_label.js index 71cc5803e01739..21435121980554 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_no_color_label.js +++ b/packages/kbn-ui-framework/doc_site/src/views/color_picker/color_picker_no_color_label.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/column/column_example.js b/packages/kbn-ui-framework/doc_site/src/views/column/column_example.js index 3910d26cfb2ac6..efd38197905629 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/column/column_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/column/column_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/context_menu/context_menu.js b/packages/kbn-ui-framework/doc_site/src/views/context_menu/context_menu.js index 24da035d710b18..0020b1bb52d37d 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/context_menu/context_menu.js +++ b/packages/kbn-ui-framework/doc_site/src/views/context_menu/context_menu.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/context_menu/context_menu_example.js b/packages/kbn-ui-framework/doc_site/src/views/context_menu/context_menu_example.js index a4c186409383b4..a1e36a85bd1b48 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/context_menu/context_menu_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/context_menu/context_menu_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/context_menu/single_panel.js b/packages/kbn-ui-framework/doc_site/src/views/context_menu/single_panel.js index e8f965a519b7e1..c9e736c3775ca8 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/context_menu/single_panel.js +++ b/packages/kbn-ui-framework/doc_site/src/views/context_menu/single_panel.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/empty_table_prompt.js b/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/empty_table_prompt.js index 5c37c132184561..7ca261afb9f758 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/empty_table_prompt.js +++ b/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/empty_table_prompt.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { KuiEmptyTablePrompt, KuiLinkButton, KuiButtonIcon } from '../../../../components'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/empty_table_prompt_example.js b/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/empty_table_prompt_example.js index 04d88fb8fa51c3..cff328d0a82996 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/empty_table_prompt_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/empty_table_prompt_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/table_with_empty_prompt.js b/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/table_with_empty_prompt.js index fcb2a1776e7fd8..01e07e873d1da1 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/table_with_empty_prompt.js +++ b/packages/kbn-ui-framework/doc_site/src/views/empty_table_prompt/table_with_empty_prompt.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/event/event.js b/packages/kbn-ui-framework/doc_site/src/views/event/event.js index aa08580f78b5e3..ec3e79f90b77b8 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/event/event.js +++ b/packages/kbn-ui-framework/doc_site/src/views/event/event.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/event/event_example.js b/packages/kbn-ui-framework/doc_site/src/views/event/event_example.js index e2400cd7031496..df79517b0e0fd2 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/event/event_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/event/event_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/event/event_menu.js b/packages/kbn-ui-framework/doc_site/src/views/event/event_menu.js index d318860999756d..c506e576606a2f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/event/event_menu.js +++ b/packages/kbn-ui-framework/doc_site/src/views/event/event_menu.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/event/events_sandbox.js b/packages/kbn-ui-framework/doc_site/src/views/event/events_sandbox.js index 3e5525cd90dbac..aad2be4dd06ac6 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/event/events_sandbox.js +++ b/packages/kbn-ui-framework/doc_site/src/views/event/events_sandbox.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/event/events_sandbox_content.js b/packages/kbn-ui-framework/doc_site/src/views/event/events_sandbox_content.js index e2455c80d0aa1f..58b54e5c0803c1 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/event/events_sandbox_content.js +++ b/packages/kbn-ui-framework/doc_site/src/views/event/events_sandbox_content.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/expression/expression.js b/packages/kbn-ui-framework/doc_site/src/views/expression/expression.js index a67deafc8c4aef..754b083c72cd1c 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/expression/expression.js +++ b/packages/kbn-ui-framework/doc_site/src/views/expression/expression.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/expression/expression_example.js b/packages/kbn-ui-framework/doc_site/src/views/expression/expression_example.js index 8a1d13302f5ae1..a18063ab3782b8 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/expression/expression_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/expression/expression_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_example.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_example.js index 078c68b3658d4e..9b4df7e98fe0e5 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grid.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grid.js index 16af42095d2b84..13b9adb6165e56 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grid.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grid.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grid_columns.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grid_columns.js index 985e6c19c1322f..f1066c1a9c0647 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grid_columns.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grid_columns.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_group.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_group.js index a2fdd3b54e80e5..9801871550e61c 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_group.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_group.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_group_wrap.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_group_wrap.js index 4f13ef6be9e67c..849fa6e71be880 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_group_wrap.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_group_wrap.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grow_numeric.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grow_numeric.js index 9ed249d857a7d8..08e966b8250b77 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grow_numeric.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grow_numeric.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grow_zero.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grow_zero.js index f25d3b0cd5246a..c132f9f6c3b870 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grow_zero.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_grow_zero.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_gutter.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_gutter.js index eaee7eccb7e7f4..8d0ca60ab9c7cc 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_gutter.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_gutter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_items.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_items.js index 12ce5b9c702389..07763d5dcb6d18 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_items.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_items.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_justify.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_justify.js index 521ba26d2f33ab..48bdaa950fc09f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_justify.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_justify.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_nest.js b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_nest.js index 21b16cf10f159b..e7fab069e1abf4 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/flex/flex_nest.js +++ b/packages/kbn-ui-framework/doc_site/src/views/flex/flex_nest.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/check_box.js b/packages/kbn-ui-framework/doc_site/src/views/form/check_box.js index 1a43dfd4535809..903307e675b939 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/check_box.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/check_box.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/form_example.js b/packages/kbn-ui-framework/doc_site/src/views/form/form_example.js index 95f07aab631b43..09ec859df6b037 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/form_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/form_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/label.js b/packages/kbn-ui-framework/doc_site/src/views/form/label.js index 5d8ba7dc3a6772..6ef679bf237c22 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/label.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/label.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { KuiLabel, diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/select.js b/packages/kbn-ui-framework/doc_site/src/views/form/select.js index 1b1a548684d04e..9231223c5ccd02 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/select.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/select.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/text_area.js b/packages/kbn-ui-framework/doc_site/src/views/form/text_area.js index c40fc03b8d7106..bcfe73be124a1d 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/text_area.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/text_area.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/text_area_non_resizable.js b/packages/kbn-ui-framework/doc_site/src/views/form/text_area_non_resizable.js index 2e5ab642b01524..0edf566a03c956 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/text_area_non_resizable.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/text_area_non_resizable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/form/text_input.js b/packages/kbn-ui-framework/doc_site/src/views/form/text_input.js index bb4c5b8890946f..8cdb7b42e816d6 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form/text_input.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form/text_input.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/form_layout/field_group.js b/packages/kbn-ui-framework/doc_site/src/views/form_layout/field_group.js index 94ed050f058296..d320e06ecdfbe4 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form_layout/field_group.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form_layout/field_group.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/form_layout/form_layout_example.js b/packages/kbn-ui-framework/doc_site/src/views/form_layout/form_layout_example.js index 3703f6a2b16fa2..69effef603317d 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/form_layout/form_layout_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/form_layout/form_layout_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/gallery/gallery.js b/packages/kbn-ui-framework/doc_site/src/views/gallery/gallery.js index 914811886a3d8f..9d349330f72e5a 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/gallery/gallery.js +++ b/packages/kbn-ui-framework/doc_site/src/views/gallery/gallery.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/gallery/gallery_example.js b/packages/kbn-ui-framework/doc_site/src/views/gallery/gallery_example.js index dd933e44fec294..8013d497728271 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/gallery/gallery_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/gallery/gallery_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar.js b/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar.js index 0f1e150be01c3a..4dc36a77de3c8a 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar.js +++ b/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_example.js b/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_example.js index 08c121e673e34f..60ddf568313a0c 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_sandbox.js b/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_sandbox.js index 1e129204e04367..c218ef0febc58c 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_sandbox.js +++ b/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_sandbox.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_sandbox_content.js b/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_sandbox_content.js index 710610353d728b..c03e4b667fcb14 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_sandbox_content.js +++ b/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_sandbox_content.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_two_sections.js b/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_two_sections.js index 7efb2e8d261fe7..d82b3a0c09e61f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_two_sections.js +++ b/packages/kbn-ui-framework/doc_site/src/views/header_bar/header_bar_two_sections.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/home/home_view.js b/packages/kbn-ui-framework/doc_site/src/views/home/home_view.js index 36d2ce17bb1c88..b321c58aba0ea8 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/home/home_view.js +++ b/packages/kbn-ui-framework/doc_site/src/views/home/home_view.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; export const HomeView = () => ( diff --git a/packages/kbn-ui-framework/doc_site/src/views/icon/icon_example.js b/packages/kbn-ui-framework/doc_site/src/views/icon/icon_example.js index 8ce850459de669..1597fdb648da7f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/icon/icon_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/icon/icon_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/info_button/info_button.js b/packages/kbn-ui-framework/doc_site/src/views/info_button/info_button.js index 8b86f56025e0bf..522ed4b0759b49 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/info_button/info_button.js +++ b/packages/kbn-ui-framework/doc_site/src/views/info_button/info_button.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/info_button/info_button_example.js b/packages/kbn-ui-framework/doc_site/src/views/info_button/info_button_example.js index 9e0e55a9414c6d..3794a3fb93d421 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/info_button/info_button_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/info_button/info_button_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/info_panel/info_panel_example.js b/packages/kbn-ui-framework/doc_site/src/views/info_panel/info_panel_example.js index 416735cb9f1dd0..7a3eaf4315255f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/info_panel/info_panel_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/info_panel/info_panel_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/link/link_example.js b/packages/kbn-ui-framework/doc_site/src/views/link/link_example.js index b9a243838f3e44..22775ffed244f0 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/link/link_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/link/link_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_breadcrumbs.js b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_breadcrumbs.js index 76a73d3ac3eb55..102cd3be0e2c97 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_breadcrumbs.js +++ b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_breadcrumbs.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_dropdown.js b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_dropdown.js index 96e9ff49fabd7a..cfe5d2091b1e38 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_dropdown.js +++ b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_dropdown.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js index f85289907fbdc5..0a6feeddf6f22a 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js +++ b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_dropdown_panels.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_example.js b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_example.js index e69178aa492382..ade78ccd26152c 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* eslint import/no-duplicates: 0, import/default: 0 */ import React from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_menu_item_states.js b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_menu_item_states.js index 382ae2660c3491..0b28873e3927ec 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_menu_item_states.js +++ b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_menu_item_states.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_search.js b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_search.js index 77337bf143f355..3453794815373c 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_search.js +++ b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_search.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_search_error.js b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_search_error.js index 878df0c7c31ef4..7974fb3acd1d1f 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_search_error.js +++ b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_search_error.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_simple.js b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_simple.js index 1b21091a84e7ef..ae240a2cee8839 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_simple.js +++ b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_simple.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_tabs.js b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_tabs.js index cb395399e6160b..e0ce27c8b80ea4 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_tabs.js +++ b/packages/kbn-ui-framework/doc_site/src/views/local_nav/local_nav_tabs.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/menu/menu.js b/packages/kbn-ui-framework/doc_site/src/views/menu/menu.js index acbc9580bd2ef0..ca9b6ccc1925f0 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/menu/menu.js +++ b/packages/kbn-ui-framework/doc_site/src/views/menu/menu.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/menu/menu_contained.js b/packages/kbn-ui-framework/doc_site/src/views/menu/menu_contained.js index 0f602976fdcc8c..0ab679613942bf 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/menu/menu_contained.js +++ b/packages/kbn-ui-framework/doc_site/src/views/menu/menu_contained.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/menu/menu_example.js b/packages/kbn-ui-framework/doc_site/src/views/menu/menu_example.js index 1b54cc0b0e90bb..4ba5b4507b2972 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/menu/menu_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/menu/menu_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/menu_button/menu_button_example.js b/packages/kbn-ui-framework/doc_site/src/views/menu_button/menu_button_example.js index 22d5f979b7dc92..ba004a15830153 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/menu_button/menu_button_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/menu_button/menu_button_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/micro_button/micro_button_example.js b/packages/kbn-ui-framework/doc_site/src/views/micro_button/micro_button_example.js index 8b0fbbc542b504..66aea530de5ca4 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/micro_button/micro_button_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/micro_button/micro_button_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/modal/confirm_modal.js b/packages/kbn-ui-framework/doc_site/src/views/modal/confirm_modal.js index 0ca84e288fd086..8ef7e88fe1496e 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/modal/confirm_modal.js +++ b/packages/kbn-ui-framework/doc_site/src/views/modal/confirm_modal.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/modal/modal.js b/packages/kbn-ui-framework/doc_site/src/views/modal/modal.js index 571aadf935eb74..52fd031ccf4282 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/modal/modal.js +++ b/packages/kbn-ui-framework/doc_site/src/views/modal/modal.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/modal/modal_example.js b/packages/kbn-ui-framework/doc_site/src/views/modal/modal_example.js index 2b2667f4330c30..3c16a52173b330 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/modal/modal_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/modal/modal_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/not_found/not_found_view.js b/packages/kbn-ui-framework/doc_site/src/views/not_found/not_found_view.js index 164179f1f9b10b..34c3a3f6bbe2e6 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/not_found/not_found_view.js +++ b/packages/kbn-ui-framework/doc_site/src/views/not_found/not_found_view.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/notice/notice_sandbox.js b/packages/kbn-ui-framework/doc_site/src/views/notice/notice_sandbox.js index 2210104a520def..84a7e2f058eea0 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/notice/notice_sandbox.js +++ b/packages/kbn-ui-framework/doc_site/src/views/notice/notice_sandbox.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/pager/pager_buttons.js b/packages/kbn-ui-framework/doc_site/src/views/pager/pager_buttons.js index 51446d70cf3333..f216f026c2c21b 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/pager/pager_buttons.js +++ b/packages/kbn-ui-framework/doc_site/src/views/pager/pager_buttons.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/pager/pager_example.js b/packages/kbn-ui-framework/doc_site/src/views/pager/pager_example.js index 2749f8e36038c9..9519b5463a46a6 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/pager/pager_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/pager/pager_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/pager/tool_bar_pager.js b/packages/kbn-ui-framework/doc_site/src/views/pager/tool_bar_pager.js index 17a9c4265c3dc6..38614f79fee509 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/pager/tool_bar_pager.js +++ b/packages/kbn-ui-framework/doc_site/src/views/pager/tool_bar_pager.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/panel/panel_example.js b/packages/kbn-ui-framework/doc_site/src/views/panel/panel_example.js index 3e15bbf7c88ecd..b5e4ae5b07ff65 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/panel/panel_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/panel/panel_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/panel_simple/panel_simple.js b/packages/kbn-ui-framework/doc_site/src/views/panel_simple/panel_simple.js index fa3012729b9b1c..376e6033583388 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/panel_simple/panel_simple.js +++ b/packages/kbn-ui-framework/doc_site/src/views/panel_simple/panel_simple.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/panel_simple/panel_simple_example.js b/packages/kbn-ui-framework/doc_site/src/views/panel_simple/panel_simple_example.js index 52311548f59d64..fd0102a23eb743 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/panel_simple/panel_simple_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/panel_simple/panel_simple_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { Link } from 'react-router'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/popover/popover.js b/packages/kbn-ui-framework/doc_site/src/views/popover/popover.js index dd8b0719db665c..59e47ef348b748 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/popover/popover.js +++ b/packages/kbn-ui-framework/doc_site/src/views/popover/popover.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/popover/popover_anchor_position.js b/packages/kbn-ui-framework/doc_site/src/views/popover/popover_anchor_position.js index d2061ed87136f3..54e0f97542acdc 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/popover/popover_anchor_position.js +++ b/packages/kbn-ui-framework/doc_site/src/views/popover/popover_anchor_position.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/popover/popover_body_class_name.js b/packages/kbn-ui-framework/doc_site/src/views/popover/popover_body_class_name.js index 0e0dd6bb8a31a3..e347c5a3211874 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/popover/popover_body_class_name.js +++ b/packages/kbn-ui-framework/doc_site/src/views/popover/popover_body_class_name.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/popover/popover_example.js b/packages/kbn-ui-framework/doc_site/src/views/popover/popover_example.js index 21c0ef939aea03..9893b443748e32 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/popover/popover_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/popover/popover_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/popover/popover_panel_class_name.js b/packages/kbn-ui-framework/doc_site/src/views/popover/popover_panel_class_name.js index 8007e87757e553..c3b98fc6ca3d13 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/popover/popover_panel_class_name.js +++ b/packages/kbn-ui-framework/doc_site/src/views/popover/popover_panel_class_name.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/popover/popover_with_title.js b/packages/kbn-ui-framework/doc_site/src/views/popover/popover_with_title.js index dcea51899e2369..ff25a54e1d60ec 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/popover/popover_with_title.js +++ b/packages/kbn-ui-framework/doc_site/src/views/popover/popover_with_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/popover/trap_focus.js b/packages/kbn-ui-framework/doc_site/src/views/popover/trap_focus.js index f96afc3444c682..b034da504f3d47 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/popover/trap_focus.js +++ b/packages/kbn-ui-framework/doc_site/src/views/popover/trap_focus.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/status_text/status_text_example.js b/packages/kbn-ui-framework/doc_site/src/views/status_text/status_text_example.js index 06e0cbfcaa5b79..9bafdf9ea40c90 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/status_text/status_text_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/status_text/status_text_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/fluid_table.js b/packages/kbn-ui-framework/doc_site/src/views/table/fluid_table.js index 512201baee496b..b0f452b218a902 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/fluid_table.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/fluid_table.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/listing_table.js b/packages/kbn-ui-framework/doc_site/src/views/table/listing_table.js index 9120a284a3290d..d41a5c5a37a1ee 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/listing_table.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/listing_table.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component } from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_loading_items.js b/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_loading_items.js index 16f7de6ab85032..d8fce0df10d84e 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_loading_items.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_loading_items.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_with_empty_prompt.js b/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_with_empty_prompt.js index 68d04335260362..53ef7cc9e75c47 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_with_empty_prompt.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_with_empty_prompt.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_with_no_items.js b/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_with_no_items.js index 3ee73b8a5a9e60..2500b4630950df 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_with_no_items.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/listing_table_with_no_items.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/table.js b/packages/kbn-ui-framework/doc_site/src/views/table/table.js index 3ff02eb4c30700..b8fde051de95c5 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/table.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/table.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/table_example.js b/packages/kbn-ui-framework/doc_site/src/views/table/table_example.js index f98b0be2698ee3..221ba988441c4b 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/table_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/table_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/table/table_with_menu_buttons.js b/packages/kbn-ui-framework/doc_site/src/views/table/table_with_menu_buttons.js index 66052a23415fb4..4b1b0638768610 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/table/table_with_menu_buttons.js +++ b/packages/kbn-ui-framework/doc_site/src/views/table/table_with_menu_buttons.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs.js b/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs.js index 6c949525f295e9..89f1f8bacda758 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs.js +++ b/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs_example.js b/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs_example.js index 2809c07127d9ec..10894503fc2b55 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/tabs/tabs_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/toggle_button/toggle_button_example.js b/packages/kbn-ui-framework/doc_site/src/views/toggle_button/toggle_button_example.js index 0f65d04682240a..a69e8c3d21b87c 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/toggle_button/toggle_button_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/toggle_button/toggle_button_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar.js b/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar.js index 603a19973f499b..6c5da4f7258616 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar.js +++ b/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar_example.js b/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar_example.js index 53b4854b3d1cd7..fa3a797472f855 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { renderToHtml } from '../../services'; diff --git a/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar_footer.js b/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar_footer.js index 379f117288adbd..aa37cb7145aab3 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar_footer.js +++ b/packages/kbn-ui-framework/doc_site/src/views/tool_bar/tool_bar_footer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/typography/typography_example.js b/packages/kbn-ui-framework/doc_site/src/views/typography/typography_example.js index 70e17d9fe7027f..17d7051908e7e0 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/typography/typography_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/typography/typography_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/vertical_rhythm/vertical_rhythm_example.js b/packages/kbn-ui-framework/doc_site/src/views/vertical_rhythm/vertical_rhythm_example.js index 5f9e4903688634..d8a559f4d4fe02 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/vertical_rhythm/vertical_rhythm_example.js +++ b/packages/kbn-ui-framework/doc_site/src/views/vertical_rhythm/vertical_rhythm_example.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/src/views/view/view_sandbox.js b/packages/kbn-ui-framework/doc_site/src/views/view/view_sandbox.js index 5710d536097f51..cf313e6c72646b 100644 --- a/packages/kbn-ui-framework/doc_site/src/views/view/view_sandbox.js +++ b/packages/kbn-ui-framework/doc_site/src/views/view/view_sandbox.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/doc_site/webpack.config.js b/packages/kbn-ui-framework/doc_site/webpack.config.js index a8cb7f03dc9592..1b2fc37c1976bc 100644 --- a/packages/kbn-ui-framework/doc_site/webpack.config.js +++ b/packages/kbn-ui-framework/doc_site/webpack.config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const path = require('path'); module.exports = { context: __dirname, @@ -27,7 +46,7 @@ module.exports = { exclude: /node_modules/, query: { presets: [ - require.resolve('@kbn/babel-preset/webpack') + require.resolve('@kbn/babel-preset/webpack_preset') ], }, }, { diff --git a/packages/kbn-ui-framework/generator-kui/app/component.js b/packages/kbn-ui-framework/generator-kui/app/component.js index 165dd19969d0f1..c648b71206059d 100644 --- a/packages/kbn-ui-framework/generator-kui/app/component.js +++ b/packages/kbn-ui-framework/generator-kui/app/component.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const Generator = require('yeoman-generator'); const componentGenerator = require.resolve('../component/index.js'); diff --git a/packages/kbn-ui-framework/generator-kui/app/documentation.js b/packages/kbn-ui-framework/generator-kui/app/documentation.js index e611013de23bd8..1e643202ad7d20 100644 --- a/packages/kbn-ui-framework/generator-kui/app/documentation.js +++ b/packages/kbn-ui-framework/generator-kui/app/documentation.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const Generator = require('yeoman-generator'); const documentationGenerator = require.resolve('../documentation/index.js'); diff --git a/packages/kbn-ui-framework/generator-kui/component/index.js b/packages/kbn-ui-framework/generator-kui/component/index.js index fa35bd40bafce4..d1030487aca920 100644 --- a/packages/kbn-ui-framework/generator-kui/component/index.js +++ b/packages/kbn-ui-framework/generator-kui/component/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const chalk = require('chalk'); const { resolve } = require('path'); const Generator = require('yeoman-generator'); diff --git a/packages/kbn-ui-framework/generator-kui/documentation/index.js b/packages/kbn-ui-framework/generator-kui/documentation/index.js index a33b55bee7a22d..64e16cb08e5679 100644 --- a/packages/kbn-ui-framework/generator-kui/documentation/index.js +++ b/packages/kbn-ui-framework/generator-kui/documentation/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const chalk = require('chalk'); const { resolve } = require('path'); const Generator = require('yeoman-generator'); diff --git a/packages/kbn-ui-framework/generator-kui/utils.js b/packages/kbn-ui-framework/generator-kui/utils.js index 05bc8a4192b932..6f7f3df2f82e0c 100644 --- a/packages/kbn-ui-framework/generator-kui/utils.js +++ b/packages/kbn-ui-framework/generator-kui/utils.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function makeComponentName(str, usePrefix = true) { const words = str.split('_'); diff --git a/packages/kbn-ui-framework/package.json b/packages/kbn-ui-framework/package.json index 3b6826c45ef4f2..9c752ae7849c0b 100644 --- a/packages/kbn-ui-framework/package.json +++ b/packages/kbn-ui-framework/package.json @@ -65,7 +65,7 @@ "redux": "3.7.2", "redux-thunk": "2.2.0", "sass-loader": "6.0.6", - "sinon": "1.17.2", + "sinon": "^5.0.7", "style-loader": "0.19.0", "webpack": "3.6.0", "webpack-dev-server": "2.9.1", diff --git a/packages/kbn-ui-framework/src/components/accessibility/index.js b/packages/kbn-ui-framework/src/components/accessibility/index.js index d847a370d0d943..013dd334ade3f4 100644 --- a/packages/kbn-ui-framework/src/components/accessibility/index.js +++ b/packages/kbn-ui-framework/src/components/accessibility/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiKeyboardAccessible } from './keyboard_accessible'; export { KuiScreenReaderOnly } from './screen_reader'; diff --git a/packages/kbn-ui-framework/src/components/accessibility/keyboard_accessible.js b/packages/kbn-ui-framework/src/components/accessibility/keyboard_accessible.js index 765db1db389625..2b1965b029a630 100644 --- a/packages/kbn-ui-framework/src/components/accessibility/keyboard_accessible.js +++ b/packages/kbn-ui-framework/src/components/accessibility/keyboard_accessible.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Interactive elements must be able to receive focus. * diff --git a/packages/kbn-ui-framework/src/components/accessibility/keyboard_accessible.test.js b/packages/kbn-ui-framework/src/components/accessibility/keyboard_accessible.test.js index b4734df641cce3..7c67b26e1a0714 100644 --- a/packages/kbn-ui-framework/src/components/accessibility/keyboard_accessible.test.js +++ b/packages/kbn-ui-framework/src/components/accessibility/keyboard_accessible.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, diff --git a/packages/kbn-ui-framework/src/components/accessibility/screen_reader.js b/packages/kbn-ui-framework/src/components/accessibility/screen_reader.js index a1d63e4a6a9e67..64f6e746144da9 100644 --- a/packages/kbn-ui-framework/src/components/accessibility/screen_reader.js +++ b/packages/kbn-ui-framework/src/components/accessibility/screen_reader.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import { cloneElement } from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/accessibility/screen_reader.test.js b/packages/kbn-ui-framework/src/components/accessibility/screen_reader.test.js index 2bdb3fb40d2135..9cf6377ce312be 100644 --- a/packages/kbn-ui-framework/src/components/accessibility/screen_reader.test.js +++ b/packages/kbn-ui-framework/src/components/accessibility/screen_reader.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; diff --git a/packages/kbn-ui-framework/src/components/action_item/action_item.js b/packages/kbn-ui-framework/src/components/action_item/action_item.js index 3551f66ffd1fd2..cc4196cd66d646 100644 --- a/packages/kbn-ui-framework/src/components/action_item/action_item.js +++ b/packages/kbn-ui-framework/src/components/action_item/action_item.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/action_item/action_item.test.js b/packages/kbn-ui-framework/src/components/action_item/action_item.test.js index 0813a95657ec72..0a930e9bb9582d 100644 --- a/packages/kbn-ui-framework/src/components/action_item/action_item.test.js +++ b/packages/kbn-ui-framework/src/components/action_item/action_item.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/action_item/index.js b/packages/kbn-ui-framework/src/components/action_item/index.js index ff88f289e2befa..b225e4aab44720 100644 --- a/packages/kbn-ui-framework/src/components/action_item/index.js +++ b/packages/kbn-ui-framework/src/components/action_item/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiActionItem } from './action_item'; diff --git a/packages/kbn-ui-framework/src/components/bar/bar.js b/packages/kbn-ui-framework/src/components/bar/bar.js index db85f8db53899c..8e78dc05d55349 100644 --- a/packages/kbn-ui-framework/src/components/bar/bar.js +++ b/packages/kbn-ui-framework/src/components/bar/bar.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/bar/bar.test.js b/packages/kbn-ui-framework/src/components/bar/bar.test.js index 4d6c009d2cb00e..366b025d6bb8d1 100644 --- a/packages/kbn-ui-framework/src/components/bar/bar.test.js +++ b/packages/kbn-ui-framework/src/components/bar/bar.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/bar/bar_section.js b/packages/kbn-ui-framework/src/components/bar/bar_section.js index a09deee31f62f2..7c4d72cd08c7c0 100644 --- a/packages/kbn-ui-framework/src/components/bar/bar_section.js +++ b/packages/kbn-ui-framework/src/components/bar/bar_section.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/bar/bar_section.test.js b/packages/kbn-ui-framework/src/components/bar/bar_section.test.js index 8ea925caef62ed..be65134e7a4efa 100644 --- a/packages/kbn-ui-framework/src/components/bar/bar_section.test.js +++ b/packages/kbn-ui-framework/src/components/bar/bar_section.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/bar/index.js b/packages/kbn-ui-framework/src/components/bar/index.js index 6cd68335956bb8..710e125bdf03ed 100644 --- a/packages/kbn-ui-framework/src/components/bar/index.js +++ b/packages/kbn-ui-framework/src/components/bar/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiBarSection } from './bar_section'; export { KuiBar } from './bar'; diff --git a/packages/kbn-ui-framework/src/components/button/button.js b/packages/kbn-ui-framework/src/components/button/button.js index 52dc9b1e7e06e2..bab250b0e05fe8 100644 --- a/packages/kbn-ui-framework/src/components/button/button.js +++ b/packages/kbn-ui-framework/src/components/button/button.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/button/button.test.js b/packages/kbn-ui-framework/src/components/button/button.test.js index 3e98776faf99c4..dacb26fab7065a 100644 --- a/packages/kbn-ui-framework/src/components/button/button.test.js +++ b/packages/kbn-ui-framework/src/components/button/button.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow } from 'enzyme'; import sinon from 'sinon'; diff --git a/packages/kbn-ui-framework/src/components/button/button_group/button_group.js b/packages/kbn-ui-framework/src/components/button/button_group/button_group.js index 6fa8b68d7476e4..49eaff03efd402 100644 --- a/packages/kbn-ui-framework/src/components/button/button_group/button_group.js +++ b/packages/kbn-ui-framework/src/components/button/button_group/button_group.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/button/button_group/button_group.test.js b/packages/kbn-ui-framework/src/components/button/button_group/button_group.test.js index 4d7ee5b90e6c03..6722b9643fd24e 100644 --- a/packages/kbn-ui-framework/src/components/button/button_group/button_group.test.js +++ b/packages/kbn-ui-framework/src/components/button/button_group/button_group.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; diff --git a/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.js b/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.js index 839a7413173c74..096e498451b091 100644 --- a/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.js +++ b/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.test.js b/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.test.js index b0c3f9d2bcd4cb..8a040c20d4c98e 100644 --- a/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.test.js +++ b/packages/kbn-ui-framework/src/components/button/button_icon/button_icon.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, diff --git a/packages/kbn-ui-framework/src/components/button/index.js b/packages/kbn-ui-framework/src/components/button/index.js index 5cc6c07bfc39c9..91bec869a1318a 100644 --- a/packages/kbn-ui-framework/src/components/button/index.js +++ b/packages/kbn-ui-framework/src/components/button/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiButton, KuiLinkButton, diff --git a/packages/kbn-ui-framework/src/components/button/link_button.test.js b/packages/kbn-ui-framework/src/components/button/link_button.test.js index 53e7e67c327691..820d1895f6bacf 100644 --- a/packages/kbn-ui-framework/src/components/button/link_button.test.js +++ b/packages/kbn-ui-framework/src/components/button/link_button.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; diff --git a/packages/kbn-ui-framework/src/components/button/submit_button.test.js b/packages/kbn-ui-framework/src/components/button/submit_button.test.js index 9d301570d523bc..c79f06f29e4237 100644 --- a/packages/kbn-ui-framework/src/components/button/submit_button.test.js +++ b/packages/kbn-ui-framework/src/components/button/submit_button.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow } from 'enzyme'; import sinon from 'sinon'; diff --git a/packages/kbn-ui-framework/src/components/card/card.js b/packages/kbn-ui-framework/src/components/card/card.js index ee0ee3b23f744c..c903685de93806 100644 --- a/packages/kbn-ui-framework/src/components/card/card.js +++ b/packages/kbn-ui-framework/src/components/card/card.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/card/card.test.js b/packages/kbn-ui-framework/src/components/card/card.test.js index bbbf2f902869e7..d54e08cf72f542 100644 --- a/packages/kbn-ui-framework/src/components/card/card.test.js +++ b/packages/kbn-ui-framework/src/components/card/card.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/card/card_description.js b/packages/kbn-ui-framework/src/components/card/card_description.js index a624b3203db875..55a5cba0911415 100644 --- a/packages/kbn-ui-framework/src/components/card/card_description.js +++ b/packages/kbn-ui-framework/src/components/card/card_description.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/card/card_description.test.js b/packages/kbn-ui-framework/src/components/card/card_description.test.js index e8bf3fec1ab92f..f3ffbeb1092233 100644 --- a/packages/kbn-ui-framework/src/components/card/card_description.test.js +++ b/packages/kbn-ui-framework/src/components/card/card_description.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/card/card_description_text.js b/packages/kbn-ui-framework/src/components/card/card_description_text.js index 26b25377e7a311..6cdd1be2d5f4b6 100644 --- a/packages/kbn-ui-framework/src/components/card/card_description_text.js +++ b/packages/kbn-ui-framework/src/components/card/card_description_text.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/card/card_description_text.test.js b/packages/kbn-ui-framework/src/components/card/card_description_text.test.js index 30de048e2782cc..3bb21077fa31e1 100644 --- a/packages/kbn-ui-framework/src/components/card/card_description_text.test.js +++ b/packages/kbn-ui-framework/src/components/card/card_description_text.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/card/card_description_title.js b/packages/kbn-ui-framework/src/components/card/card_description_title.js index 33abea3adc43c7..c6bbc63aa1cb6b 100644 --- a/packages/kbn-ui-framework/src/components/card/card_description_title.js +++ b/packages/kbn-ui-framework/src/components/card/card_description_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/card/card_description_title.test.js b/packages/kbn-ui-framework/src/components/card/card_description_title.test.js index 5dd0ed13113558..431daace1e3a33 100644 --- a/packages/kbn-ui-framework/src/components/card/card_description_title.test.js +++ b/packages/kbn-ui-framework/src/components/card/card_description_title.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/card/card_footer.js b/packages/kbn-ui-framework/src/components/card/card_footer.js index 8137459ec5f9e4..21015f26bef116 100644 --- a/packages/kbn-ui-framework/src/components/card/card_footer.js +++ b/packages/kbn-ui-framework/src/components/card/card_footer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/card/card_footer.test.js b/packages/kbn-ui-framework/src/components/card/card_footer.test.js index c1e059147558f1..0f7b4dc7544f81 100644 --- a/packages/kbn-ui-framework/src/components/card/card_footer.test.js +++ b/packages/kbn-ui-framework/src/components/card/card_footer.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/card/card_group.js b/packages/kbn-ui-framework/src/components/card/card_group.js index 3570c4ed81d90d..0e47b7ac3f58f0 100644 --- a/packages/kbn-ui-framework/src/components/card/card_group.js +++ b/packages/kbn-ui-framework/src/components/card/card_group.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/card/card_group.test.js b/packages/kbn-ui-framework/src/components/card/card_group.test.js index ed3013c1020705..4635adb5960a9d 100644 --- a/packages/kbn-ui-framework/src/components/card/card_group.test.js +++ b/packages/kbn-ui-framework/src/components/card/card_group.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/card/index.js b/packages/kbn-ui-framework/src/components/card/index.js index 7310dc9e79ac71..d54004301c8123 100644 --- a/packages/kbn-ui-framework/src/components/card/index.js +++ b/packages/kbn-ui-framework/src/components/card/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiCard } from './card'; export { KuiCardDescriptionText } from './card_description_text'; export { KuiCardDescriptionTitle } from './card_description_title'; diff --git a/packages/kbn-ui-framework/src/components/code_editor/code_editor.js b/packages/kbn-ui-framework/src/components/code_editor/code_editor.js index e99ceb127e69e5..bdb01d87517e7e 100644 --- a/packages/kbn-ui-framework/src/components/code_editor/code_editor.js +++ b/packages/kbn-ui-framework/src/components/code_editor/code_editor.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/code_editor/code_editor.test.js b/packages/kbn-ui-framework/src/components/code_editor/code_editor.test.js index 7333d536e2f70c..d223c6cd57dc5d 100644 --- a/packages/kbn-ui-framework/src/components/code_editor/code_editor.test.js +++ b/packages/kbn-ui-framework/src/components/code_editor/code_editor.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import sinon from 'sinon'; import { mount } from 'enzyme'; diff --git a/packages/kbn-ui-framework/src/components/code_editor/index.js b/packages/kbn-ui-framework/src/components/code_editor/index.js index dd346795afbe68..812a64c7738224 100644 --- a/packages/kbn-ui-framework/src/components/code_editor/index.js +++ b/packages/kbn-ui-framework/src/components/code_editor/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiCodeEditor } from './code_editor'; diff --git a/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.js b/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.js index 7a58119b524d6e..da1b0fcbd60334 100644 --- a/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.js +++ b/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.test.js b/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.test.js index d7a20a6af8e7e1..b4a22b7cb34858 100644 --- a/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.test.js +++ b/packages/kbn-ui-framework/src/components/collapse_button/collapse_button.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/collapse_button/index.js b/packages/kbn-ui-framework/src/components/collapse_button/index.js index 5f3cb43b9d295f..e44f439c27e3d4 100644 --- a/packages/kbn-ui-framework/src/components/collapse_button/index.js +++ b/packages/kbn-ui-framework/src/components/collapse_button/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiCollapseButton } from './collapse_button'; diff --git a/packages/kbn-ui-framework/src/components/color_picker/color_picker.js b/packages/kbn-ui-framework/src/components/color_picker/color_picker.js index 41965cb48a4187..eca0d89834220a 100644 --- a/packages/kbn-ui-framework/src/components/color_picker/color_picker.js +++ b/packages/kbn-ui-framework/src/components/color_picker/color_picker.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/color_picker/color_picker.test.js b/packages/kbn-ui-framework/src/components/color_picker/color_picker.test.js index b1c8ca61f5208a..2111b63d57ebe7 100644 --- a/packages/kbn-ui-framework/src/components/color_picker/color_picker.test.js +++ b/packages/kbn-ui-framework/src/components/color_picker/color_picker.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, mount } from 'enzyme'; import sinon from 'sinon'; diff --git a/packages/kbn-ui-framework/src/components/color_picker/color_picker_empty_swatch.js b/packages/kbn-ui-framework/src/components/color_picker/color_picker_empty_swatch.js index d94475fa6467f0..9b41ce5c4d69d5 100644 --- a/packages/kbn-ui-framework/src/components/color_picker/color_picker_empty_swatch.js +++ b/packages/kbn-ui-framework/src/components/color_picker/color_picker_empty_swatch.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; export function KuiColorPickerEmptySwatch() { diff --git a/packages/kbn-ui-framework/src/components/color_picker/color_picker_swatch.js b/packages/kbn-ui-framework/src/components/color_picker/color_picker_swatch.js index 93bdd6b07b1e37..647235fa3a6e04 100644 --- a/packages/kbn-ui-framework/src/components/color_picker/color_picker_swatch.js +++ b/packages/kbn-ui-framework/src/components/color_picker/color_picker_swatch.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/color_picker/index.js b/packages/kbn-ui-framework/src/components/color_picker/index.js index e06c941c388b4e..e902e1b7f62a3d 100644 --- a/packages/kbn-ui-framework/src/components/color_picker/index.js +++ b/packages/kbn-ui-framework/src/components/color_picker/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiColorPicker } from './color_picker'; diff --git a/packages/kbn-ui-framework/src/components/context_menu/context_menu.js b/packages/kbn-ui-framework/src/components/context_menu/context_menu.js index aad785a6c1a920..909baed1e76fa8 100644 --- a/packages/kbn-ui-framework/src/components/context_menu/context_menu.js +++ b/packages/kbn-ui-framework/src/components/context_menu/context_menu.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/src/components/context_menu/context_menu.test.js b/packages/kbn-ui-framework/src/components/context_menu/context_menu.test.js index 13cc1484900479..f176139b54046d 100644 --- a/packages/kbn-ui-framework/src/components/context_menu/context_menu.test.js +++ b/packages/kbn-ui-framework/src/components/context_menu/context_menu.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, mount } from 'enzyme'; import { diff --git a/packages/kbn-ui-framework/src/components/context_menu/context_menu_item.js b/packages/kbn-ui-framework/src/components/context_menu/context_menu_item.js index a0ab5e931850af..79973f9474db64 100644 --- a/packages/kbn-ui-framework/src/components/context_menu/context_menu_item.js +++ b/packages/kbn-ui-framework/src/components/context_menu/context_menu_item.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { cloneElement, Component, diff --git a/packages/kbn-ui-framework/src/components/context_menu/context_menu_item.test.js b/packages/kbn-ui-framework/src/components/context_menu/context_menu_item.test.js index be6bbdeee0f88a..cf542b9a37e24a 100644 --- a/packages/kbn-ui-framework/src/components/context_menu/context_menu_item.test.js +++ b/packages/kbn-ui-framework/src/components/context_menu/context_menu_item.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow, mount } from 'enzyme'; import sinon from 'sinon'; diff --git a/packages/kbn-ui-framework/src/components/context_menu/context_menu_panel.js b/packages/kbn-ui-framework/src/components/context_menu/context_menu_panel.js index 2ea7e1712b59f2..2e3c18f1448d29 100644 --- a/packages/kbn-ui-framework/src/components/context_menu/context_menu_panel.js +++ b/packages/kbn-ui-framework/src/components/context_menu/context_menu_panel.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { cloneElement, Component, diff --git a/packages/kbn-ui-framework/src/components/context_menu/context_menu_panel.test.js b/packages/kbn-ui-framework/src/components/context_menu/context_menu_panel.test.js index bc20e0585dd3ab..0fc524d33dacfb 100644 --- a/packages/kbn-ui-framework/src/components/context_menu/context_menu_panel.test.js +++ b/packages/kbn-ui-framework/src/components/context_menu/context_menu_panel.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, mount } from 'enzyme'; import sinon from 'sinon'; diff --git a/packages/kbn-ui-framework/src/components/context_menu/index.js b/packages/kbn-ui-framework/src/components/context_menu/index.js index 95ca6f3654ff10..af72085105975f 100644 --- a/packages/kbn-ui-framework/src/components/context_menu/index.js +++ b/packages/kbn-ui-framework/src/components/context_menu/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiContextMenu, } from './context_menu'; diff --git a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt.js b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt.js index 1d99b777b254e1..46ae99cb401ac8 100644 --- a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt.js +++ b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classnames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt.test.js b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt.test.js index 300bc1ab3aac0b..ccd30a76b3b172 100644 --- a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt.test.js +++ b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_actions.js b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_actions.js index 9129fabba9c04e..0447feddc2e76e 100644 --- a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_actions.js +++ b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_actions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_actions.test.js b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_actions.test.js index c4ee0459315944..bebd991b7f411a 100644 --- a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_actions.test.js +++ b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_actions.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_message.js b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_message.js index 19d6311bb3d672..1ca3892d69aeda 100644 --- a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_message.js +++ b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_message.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_message.test.js b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_message.test.js index 069ed8e24fdf13..8dcb83bdfba2fc 100644 --- a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_message.test.js +++ b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_message.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_panel.js b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_panel.js index 54d9ddc589764e..5d83ad896a42fb 100644 --- a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_panel.js +++ b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_panel.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_panel.test.js b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_panel.test.js index 676432e6c6b4dc..b3f936902faebb 100644 --- a/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_panel.test.js +++ b/packages/kbn-ui-framework/src/components/empty_table_prompt/empty_table_prompt_panel.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/empty_table_prompt/index.js b/packages/kbn-ui-framework/src/components/empty_table_prompt/index.js index 24058c75392e15..42e57521e46f32 100644 --- a/packages/kbn-ui-framework/src/components/empty_table_prompt/index.js +++ b/packages/kbn-ui-framework/src/components/empty_table_prompt/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiEmptyTablePromptMessage } from './empty_table_prompt_message'; export { KuiEmptyTablePromptPanel } from './empty_table_prompt_panel'; export { KuiEmptyTablePrompt } from './empty_table_prompt'; diff --git a/packages/kbn-ui-framework/src/components/event/event.js b/packages/kbn-ui-framework/src/components/event/event.js index 77646fff76f301..4566249c3fd7e8 100644 --- a/packages/kbn-ui-framework/src/components/event/event.js +++ b/packages/kbn-ui-framework/src/components/event/event.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/event/event.test.js b/packages/kbn-ui-framework/src/components/event/event.test.js index 6de87e616e4a1f..936b1efb8502c8 100644 --- a/packages/kbn-ui-framework/src/components/event/event.test.js +++ b/packages/kbn-ui-framework/src/components/event/event.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/event/event_body.js b/packages/kbn-ui-framework/src/components/event/event_body.js index e793c14b72a72b..2cd39bba48cfb5 100644 --- a/packages/kbn-ui-framework/src/components/event/event_body.js +++ b/packages/kbn-ui-framework/src/components/event/event_body.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/event/event_body.test.js b/packages/kbn-ui-framework/src/components/event/event_body.test.js index 436e41bf14dd77..989645c10e9a9e 100644 --- a/packages/kbn-ui-framework/src/components/event/event_body.test.js +++ b/packages/kbn-ui-framework/src/components/event/event_body.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/event/event_body_message.js b/packages/kbn-ui-framework/src/components/event/event_body_message.js index e748dc8da7ea45..9e595a276cbf34 100644 --- a/packages/kbn-ui-framework/src/components/event/event_body_message.js +++ b/packages/kbn-ui-framework/src/components/event/event_body_message.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/event/event_body_message.test.js b/packages/kbn-ui-framework/src/components/event/event_body_message.test.js index ee212a2d7f72ad..4d4bc4ceba2540 100644 --- a/packages/kbn-ui-framework/src/components/event/event_body_message.test.js +++ b/packages/kbn-ui-framework/src/components/event/event_body_message.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/event/event_body_metadata.js b/packages/kbn-ui-framework/src/components/event/event_body_metadata.js index 9b48bb9c8c3ec3..6154d70086512d 100644 --- a/packages/kbn-ui-framework/src/components/event/event_body_metadata.js +++ b/packages/kbn-ui-framework/src/components/event/event_body_metadata.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/event/event_body_metadata.test.js b/packages/kbn-ui-framework/src/components/event/event_body_metadata.test.js index 164c0fa0abbf8e..76c2cd0d8e70cf 100644 --- a/packages/kbn-ui-framework/src/components/event/event_body_metadata.test.js +++ b/packages/kbn-ui-framework/src/components/event/event_body_metadata.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/event/event_symbol.js b/packages/kbn-ui-framework/src/components/event/event_symbol.js index 075ed90067f951..ad2c6f46790427 100644 --- a/packages/kbn-ui-framework/src/components/event/event_symbol.js +++ b/packages/kbn-ui-framework/src/components/event/event_symbol.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/event/event_symbol.test.js b/packages/kbn-ui-framework/src/components/event/event_symbol.test.js index 903c48dd3fb35d..145c59dadebf9d 100644 --- a/packages/kbn-ui-framework/src/components/event/event_symbol.test.js +++ b/packages/kbn-ui-framework/src/components/event/event_symbol.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/event/index.js b/packages/kbn-ui-framework/src/components/event/index.js index 031f98eda1eb0e..9109f08282e967 100644 --- a/packages/kbn-ui-framework/src/components/event/index.js +++ b/packages/kbn-ui-framework/src/components/event/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiEvent } from './event'; export { KuiEventSymbol } from './event_symbol'; export { KuiEventBody } from './event_body'; diff --git a/packages/kbn-ui-framework/src/components/expression/expression.js b/packages/kbn-ui-framework/src/components/expression/expression.js index dadd8db2819b98..4464a1b742ba11 100644 --- a/packages/kbn-ui-framework/src/components/expression/expression.js +++ b/packages/kbn-ui-framework/src/components/expression/expression.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/expression/expression.test.js b/packages/kbn-ui-framework/src/components/expression/expression.test.js index acf34e19dfbdbd..5043dff09aa342 100644 --- a/packages/kbn-ui-framework/src/components/expression/expression.test.js +++ b/packages/kbn-ui-framework/src/components/expression/expression.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/expression/expression_button.js b/packages/kbn-ui-framework/src/components/expression/expression_button.js index 3e950c8845a6bd..fd63469c1eff38 100644 --- a/packages/kbn-ui-framework/src/components/expression/expression_button.js +++ b/packages/kbn-ui-framework/src/components/expression/expression_button.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/expression/expression_button.test.js b/packages/kbn-ui-framework/src/components/expression/expression_button.test.js index 01147c87c47836..69149b947662f9 100644 --- a/packages/kbn-ui-framework/src/components/expression/expression_button.test.js +++ b/packages/kbn-ui-framework/src/components/expression/expression_button.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/expression/index.js b/packages/kbn-ui-framework/src/components/expression/index.js index fd5fc718cead2d..387e42553a6223 100644 --- a/packages/kbn-ui-framework/src/components/expression/index.js +++ b/packages/kbn-ui-framework/src/components/expression/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiExpression } from './expression'; export { KuiExpressionButton } from './expression_button'; diff --git a/packages/kbn-ui-framework/src/components/flex/flex_grid.js b/packages/kbn-ui-framework/src/components/flex/flex_grid.js index 84d37059b0fa0c..f123bc9d9684f3 100644 --- a/packages/kbn-ui-framework/src/components/flex/flex_grid.js +++ b/packages/kbn-ui-framework/src/components/flex/flex_grid.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/flex/flex_grid.test.js b/packages/kbn-ui-framework/src/components/flex/flex_grid.test.js index 9f4b344c3b6e25..8cb937199ae97b 100644 --- a/packages/kbn-ui-framework/src/components/flex/flex_grid.test.js +++ b/packages/kbn-ui-framework/src/components/flex/flex_grid.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/flex/flex_group.js b/packages/kbn-ui-framework/src/components/flex/flex_group.js index fc0b66a2ec5298..eeaf6071c3531f 100644 --- a/packages/kbn-ui-framework/src/components/flex/flex_group.js +++ b/packages/kbn-ui-framework/src/components/flex/flex_group.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/flex/flex_group.test.js b/packages/kbn-ui-framework/src/components/flex/flex_group.test.js index 302b539c431092..270b3f9f509154 100644 --- a/packages/kbn-ui-framework/src/components/flex/flex_group.test.js +++ b/packages/kbn-ui-framework/src/components/flex/flex_group.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/flex/flex_item.js b/packages/kbn-ui-framework/src/components/flex/flex_item.js index eeabc214de0afd..bee553936546bc 100644 --- a/packages/kbn-ui-framework/src/components/flex/flex_item.js +++ b/packages/kbn-ui-framework/src/components/flex/flex_item.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/flex/flex_item.test.js b/packages/kbn-ui-framework/src/components/flex/flex_item.test.js index d9fdd02f35ae0d..aebd9db0f9c8f1 100644 --- a/packages/kbn-ui-framework/src/components/flex/flex_item.test.js +++ b/packages/kbn-ui-framework/src/components/flex/flex_item.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/flex/index.js b/packages/kbn-ui-framework/src/components/flex/index.js index 58d7d3fb8df32e..aa57b2e5dbc849 100644 --- a/packages/kbn-ui-framework/src/components/flex/index.js +++ b/packages/kbn-ui-framework/src/components/flex/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiFlexGroup, } from './flex_group'; diff --git a/packages/kbn-ui-framework/src/components/form/check_box/check_box.js b/packages/kbn-ui-framework/src/components/form/check_box/check_box.js index 04099890bf2ed6..74ba1f08e72aac 100644 --- a/packages/kbn-ui-framework/src/components/form/check_box/check_box.js +++ b/packages/kbn-ui-framework/src/components/form/check_box/check_box.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/form/check_box/check_box.test.js b/packages/kbn-ui-framework/src/components/form/check_box/check_box.test.js index ef46938d9bcd5b..fba64b0b4761f3 100644 --- a/packages/kbn-ui-framework/src/components/form/check_box/check_box.test.js +++ b/packages/kbn-ui-framework/src/components/form/check_box/check_box.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow } from 'enzyme'; import { requiredProps } from '../../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/form/check_box/check_box_label.js b/packages/kbn-ui-framework/src/components/form/check_box/check_box_label.js index 4842356cdf1b21..cb2c1dd57760ca 100644 --- a/packages/kbn-ui-framework/src/components/form/check_box/check_box_label.js +++ b/packages/kbn-ui-framework/src/components/form/check_box/check_box_label.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/form/check_box/check_box_label.test.js b/packages/kbn-ui-framework/src/components/form/check_box/check_box_label.test.js index 92a6f0e8dab36d..52e518863e738e 100644 --- a/packages/kbn-ui-framework/src/components/form/check_box/check_box_label.test.js +++ b/packages/kbn-ui-framework/src/components/form/check_box/check_box_label.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow } from 'enzyme'; import { requiredProps } from '../../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/form/check_box/index.js b/packages/kbn-ui-framework/src/components/form/check_box/index.js index d0a11c81ac0bb8..f4987177f12934 100644 --- a/packages/kbn-ui-framework/src/components/form/check_box/index.js +++ b/packages/kbn-ui-framework/src/components/form/check_box/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiCheckBox } from './check_box'; export { KuiCheckBoxLabel } from './check_box_label'; diff --git a/packages/kbn-ui-framework/src/components/form/index.js b/packages/kbn-ui-framework/src/components/form/index.js index b559fcf57272ec..126097b3f42ab8 100644 --- a/packages/kbn-ui-framework/src/components/form/index.js +++ b/packages/kbn-ui-framework/src/components/form/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiLabel } from './label'; export { KuiTextInput } from './text_input'; export { KuiTextArea } from './text_area'; diff --git a/packages/kbn-ui-framework/src/components/form/label/index.js b/packages/kbn-ui-framework/src/components/form/label/index.js index 5d29f0e5f7932e..8f6ffc272e45e0 100644 --- a/packages/kbn-ui-framework/src/components/form/label/index.js +++ b/packages/kbn-ui-framework/src/components/form/label/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiLabel } from './label'; diff --git a/packages/kbn-ui-framework/src/components/form/label/label.js b/packages/kbn-ui-framework/src/components/form/label/label.js index 346360622c2329..954fa8d24a2a6f 100644 --- a/packages/kbn-ui-framework/src/components/form/label/label.js +++ b/packages/kbn-ui-framework/src/components/form/label/label.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/form/label/label.test.js b/packages/kbn-ui-framework/src/components/form/label/label.test.js index 28f2bc37afd098..ec215f051c5a92 100644 --- a/packages/kbn-ui-framework/src/components/form/label/label.test.js +++ b/packages/kbn-ui-framework/src/components/form/label/label.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/form/select/index.js b/packages/kbn-ui-framework/src/components/form/select/index.js index b006942416d67d..fc94512eeaa04b 100644 --- a/packages/kbn-ui-framework/src/components/form/select/index.js +++ b/packages/kbn-ui-framework/src/components/form/select/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiSelect } from './select'; diff --git a/packages/kbn-ui-framework/src/components/form/select/select.js b/packages/kbn-ui-framework/src/components/form/select/select.js index aeace149021934..bc373cf8c5c614 100644 --- a/packages/kbn-ui-framework/src/components/form/select/select.js +++ b/packages/kbn-ui-framework/src/components/form/select/select.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/form/select/select.test.js b/packages/kbn-ui-framework/src/components/form/select/select.test.js index 5081c84423d64f..b1c9e2a7264d4d 100644 --- a/packages/kbn-ui-framework/src/components/form/select/select.test.js +++ b/packages/kbn-ui-framework/src/components/form/select/select.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow } from 'enzyme'; import { requiredProps } from '../../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/form/text_area/index.js b/packages/kbn-ui-framework/src/components/form/text_area/index.js index 6d9dfe10b23dc5..0328c65b1a4c16 100644 --- a/packages/kbn-ui-framework/src/components/form/text_area/index.js +++ b/packages/kbn-ui-framework/src/components/form/text_area/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiTextArea } from './text_area'; diff --git a/packages/kbn-ui-framework/src/components/form/text_area/text_area.js b/packages/kbn-ui-framework/src/components/form/text_area/text_area.js index 00e011a3439072..93e0e0115a3b69 100644 --- a/packages/kbn-ui-framework/src/components/form/text_area/text_area.js +++ b/packages/kbn-ui-framework/src/components/form/text_area/text_area.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/form/text_area/text_area.test.js b/packages/kbn-ui-framework/src/components/form/text_area/text_area.test.js index 8c21c4c30be744..b045bc1d0ee6b4 100644 --- a/packages/kbn-ui-framework/src/components/form/text_area/text_area.test.js +++ b/packages/kbn-ui-framework/src/components/form/text_area/text_area.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow } from 'enzyme'; import { requiredProps } from '../../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/form/text_input/index.js b/packages/kbn-ui-framework/src/components/form/text_input/index.js index ba7a0e4de0efe5..b9f92699142a76 100644 --- a/packages/kbn-ui-framework/src/components/form/text_input/index.js +++ b/packages/kbn-ui-framework/src/components/form/text_input/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiTextInput } from './text_input'; diff --git a/packages/kbn-ui-framework/src/components/form/text_input/text_input.js b/packages/kbn-ui-framework/src/components/form/text_input/text_input.js index a51119405cbbdf..5cacb51dde594e 100644 --- a/packages/kbn-ui-framework/src/components/form/text_input/text_input.js +++ b/packages/kbn-ui-framework/src/components/form/text_input/text_input.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/form/text_input/text_input.test.js b/packages/kbn-ui-framework/src/components/form/text_input/text_input.test.js index 5a6589b38f1cab..b3644efb285f87 100644 --- a/packages/kbn-ui-framework/src/components/form/text_input/text_input.test.js +++ b/packages/kbn-ui-framework/src/components/form/text_input/text_input.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow, mount } from 'enzyme'; import { requiredProps, findTestSubject } from '../../../test'; diff --git a/packages/kbn-ui-framework/src/components/form_layout/field_group.js b/packages/kbn-ui-framework/src/components/form_layout/field_group.js index 61a402e90c32c2..32d447dcb9c15f 100644 --- a/packages/kbn-ui-framework/src/components/form_layout/field_group.js +++ b/packages/kbn-ui-framework/src/components/form_layout/field_group.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/form_layout/field_group.test.js b/packages/kbn-ui-framework/src/components/form_layout/field_group.test.js index 8551fbf4d4e5b0..3318e15a888563 100644 --- a/packages/kbn-ui-framework/src/components/form_layout/field_group.test.js +++ b/packages/kbn-ui-framework/src/components/form_layout/field_group.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/form_layout/field_group_section.js b/packages/kbn-ui-framework/src/components/form_layout/field_group_section.js index 45cdf8928013c4..39ed8fef739738 100644 --- a/packages/kbn-ui-framework/src/components/form_layout/field_group_section.js +++ b/packages/kbn-ui-framework/src/components/form_layout/field_group_section.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/form_layout/field_group_section.test.js b/packages/kbn-ui-framework/src/components/form_layout/field_group_section.test.js index ac044fdfe1a127..c1b29d11d0cdc7 100644 --- a/packages/kbn-ui-framework/src/components/form_layout/field_group_section.test.js +++ b/packages/kbn-ui-framework/src/components/form_layout/field_group_section.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/form_layout/index.js b/packages/kbn-ui-framework/src/components/form_layout/index.js index a641517fa5e7d0..c3f0742e213656 100644 --- a/packages/kbn-ui-framework/src/components/form_layout/index.js +++ b/packages/kbn-ui-framework/src/components/form_layout/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiFieldGroup } from './field_group'; export { KuiFieldGroupSection } from './field_group_section'; diff --git a/packages/kbn-ui-framework/src/components/gallery/gallery.js b/packages/kbn-ui-framework/src/components/gallery/gallery.js index d2d72e89f55075..0b04d31d14c9cb 100644 --- a/packages/kbn-ui-framework/src/components/gallery/gallery.js +++ b/packages/kbn-ui-framework/src/components/gallery/gallery.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/gallery/gallery.test.js b/packages/kbn-ui-framework/src/components/gallery/gallery.test.js index 68917892dc5466..4549eea2cc692e 100644 --- a/packages/kbn-ui-framework/src/components/gallery/gallery.test.js +++ b/packages/kbn-ui-framework/src/components/gallery/gallery.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item.js b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item.js index eeb3ea8ec0a412..a2f15760ceab5d 100644 --- a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item.js +++ b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item.test.js b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item.test.js index 76bbc5ad548519..8fb01c6e7de5da 100644 --- a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item.test.js +++ b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import sinon from 'sinon'; import { render, shallow } from 'enzyme'; diff --git a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_icon.js b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_icon.js index a420ceabe34b0a..565a39e8205239 100644 --- a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_icon.js +++ b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_icon.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_icon.test.js b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_icon.test.js index 6913d77f6e7668..acecff8278b0d8 100644 --- a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_icon.test.js +++ b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_icon.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_image.js b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_image.js index 59e7fe7e4b7296..f6b6bc648c700b 100644 --- a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_image.js +++ b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_image.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_image.test.js b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_image.test.js index d30b51103bd252..c41392ab58c050 100644 --- a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_image.test.js +++ b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_image.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_label.js b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_label.js index f0045733129e59..16f7cd0797e569 100644 --- a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_label.js +++ b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_label.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_label.test.js b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_label.test.js index fbb187761b3c7b..ac1b895251f3a8 100644 --- a/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_label.test.js +++ b/packages/kbn-ui-framework/src/components/gallery/gallery_item/gallery_item_label.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/gallery/index.js b/packages/kbn-ui-framework/src/components/gallery/index.js index 72c5eb860a167a..d8e32c08742652 100644 --- a/packages/kbn-ui-framework/src/components/gallery/index.js +++ b/packages/kbn-ui-framework/src/components/gallery/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiGallery } from './gallery'; export { KuiGalleryItem } from './gallery_item/gallery_item.js'; export { KuiGalleryItemIcon } from './gallery_item/gallery_item_icon.js'; diff --git a/packages/kbn-ui-framework/src/components/header_bar/header_bar.js b/packages/kbn-ui-framework/src/components/header_bar/header_bar.js index 78620427e05ac7..0c40122724fe9f 100644 --- a/packages/kbn-ui-framework/src/components/header_bar/header_bar.js +++ b/packages/kbn-ui-framework/src/components/header_bar/header_bar.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/header_bar/header_bar.test.js b/packages/kbn-ui-framework/src/components/header_bar/header_bar.test.js index a16ef1ee6cd59b..c5cbfa8bef5506 100644 --- a/packages/kbn-ui-framework/src/components/header_bar/header_bar.test.js +++ b/packages/kbn-ui-framework/src/components/header_bar/header_bar.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/header_bar/header_bar_section.js b/packages/kbn-ui-framework/src/components/header_bar/header_bar_section.js index cf1143e412fad9..bee05e84f8b67f 100644 --- a/packages/kbn-ui-framework/src/components/header_bar/header_bar_section.js +++ b/packages/kbn-ui-framework/src/components/header_bar/header_bar_section.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/header_bar/header_bar_section.test.js b/packages/kbn-ui-framework/src/components/header_bar/header_bar_section.test.js index e183e2cd1c74a0..7e535beb4f5a44 100644 --- a/packages/kbn-ui-framework/src/components/header_bar/header_bar_section.test.js +++ b/packages/kbn-ui-framework/src/components/header_bar/header_bar_section.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/header_bar/index.js b/packages/kbn-ui-framework/src/components/header_bar/index.js index ba5b2f7728b812..80cf02ff1bc816 100644 --- a/packages/kbn-ui-framework/src/components/header_bar/index.js +++ b/packages/kbn-ui-framework/src/components/header_bar/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiHeaderBar } from './header_bar'; export { KuiHeaderBarSection } from './header_bar_section'; diff --git a/packages/kbn-ui-framework/src/components/index.js b/packages/kbn-ui-framework/src/components/index.js index e6871d8d3710cd..65ac66c71a1825 100644 --- a/packages/kbn-ui-framework/src/components/index.js +++ b/packages/kbn-ui-framework/src/components/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiActionItem } from './action_item'; export { diff --git a/packages/kbn-ui-framework/src/components/info_button/index.js b/packages/kbn-ui-framework/src/components/info_button/index.js index b0ce3214fb384c..7d7000481d4b6c 100644 --- a/packages/kbn-ui-framework/src/components/info_button/index.js +++ b/packages/kbn-ui-framework/src/components/info_button/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiInfoButton } from './info_button'; diff --git a/packages/kbn-ui-framework/src/components/info_button/info_button.js b/packages/kbn-ui-framework/src/components/info_button/info_button.js index f2cb14603ddfe2..5c2dc70172ed70 100644 --- a/packages/kbn-ui-framework/src/components/info_button/info_button.js +++ b/packages/kbn-ui-framework/src/components/info_button/info_button.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/info_button/info_button.test.js b/packages/kbn-ui-framework/src/components/info_button/info_button.test.js index 4599423b90322e..34acfa15257ace 100644 --- a/packages/kbn-ui-framework/src/components/info_button/info_button.test.js +++ b/packages/kbn-ui-framework/src/components/info_button/info_button.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/index.js b/packages/kbn-ui-framework/src/components/local_nav/index.js index 7b675c7af3838b..6bdb2fbdda5ac7 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/index.js +++ b/packages/kbn-ui-framework/src/components/local_nav/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiLocalNav } from './local_nav'; export { KuiLocalNavRow } from './local_nav_row'; export { KuiLocalNavRowSection } from './local_nav_row_section'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_nav.js b/packages/kbn-ui-framework/src/components/local_nav/local_nav.js index d70e3c24f3d47c..ef0fc752e62b2a 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_nav.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_nav.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import classnames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_nav.test.js b/packages/kbn-ui-framework/src/components/local_nav/local_nav.test.js index 2c1d5b8a9edad3..5df7111a3b065a 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_nav.test.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_nav.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_nav_row.js b/packages/kbn-ui-framework/src/components/local_nav/local_nav_row.js index 2d9b577abb3ccb..d75d1299d1b8cb 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_nav_row.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_nav_row.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import classnames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_nav_row.test.js b/packages/kbn-ui-framework/src/components/local_nav/local_nav_row.test.js index 0bd55a22a9fa9f..1e4b9a0e78697a 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_nav_row.test.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_nav_row.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_nav_row_section.js b/packages/kbn-ui-framework/src/components/local_nav/local_nav_row_section.js index 541a60d9f57c11..023aa3aaa61e38 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_nav_row_section.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_nav_row_section.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import classnames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_nav_row_section.test.js b/packages/kbn-ui-framework/src/components/local_nav/local_nav_row_section.test.js index dbc95091771278..c24eecc0229fd5 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_nav_row_section.test.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_nav_row_section.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_tab.js b/packages/kbn-ui-framework/src/components/local_nav/local_tab.js index 823bf4eabbb441..2653b118489458 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_tab.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_tab.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import classnames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_tab.test.js b/packages/kbn-ui-framework/src/components/local_nav/local_tab.test.js index 3dc458768d155c..c001303136cccf 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_tab.test.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_tab.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_tabs.js b/packages/kbn-ui-framework/src/components/local_nav/local_tabs.js index f65f5fe905215c..51954b6506a0f7 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_tabs.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_tabs.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import classnames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_tabs.test.js b/packages/kbn-ui-framework/src/components/local_nav/local_tabs.test.js index 094495ad0f897e..2ed012b1d2e27b 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_tabs.test.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_tabs.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_title.js b/packages/kbn-ui-framework/src/components/local_nav/local_title.js index 0f40d5c198198f..9dd14750370db6 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_title.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import classnames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/local_nav/local_title.test.js b/packages/kbn-ui-framework/src/components/local_nav/local_title.test.js index 17d3877f4cadf6..12fa1be63fd95a 100644 --- a/packages/kbn-ui-framework/src/components/local_nav/local_title.test.js +++ b/packages/kbn-ui-framework/src/components/local_nav/local_title.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/menu/index.js b/packages/kbn-ui-framework/src/components/menu/index.js index 0fa67b1c171fc4..54a6e4e1d82dd2 100644 --- a/packages/kbn-ui-framework/src/components/menu/index.js +++ b/packages/kbn-ui-framework/src/components/menu/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiMenu } from './menu'; export { KuiMenuItem } from './menu_item'; diff --git a/packages/kbn-ui-framework/src/components/menu/menu.js b/packages/kbn-ui-framework/src/components/menu/menu.js index 2d2ded02124aa2..e0707293cca654 100644 --- a/packages/kbn-ui-framework/src/components/menu/menu.js +++ b/packages/kbn-ui-framework/src/components/menu/menu.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/menu/menu.test.js b/packages/kbn-ui-framework/src/components/menu/menu.test.js index 265703fed390e3..1ea1e5044faa70 100644 --- a/packages/kbn-ui-framework/src/components/menu/menu.test.js +++ b/packages/kbn-ui-framework/src/components/menu/menu.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/menu/menu_item.js b/packages/kbn-ui-framework/src/components/menu/menu_item.js index 3211dd1685d690..b81d2053f75b10 100644 --- a/packages/kbn-ui-framework/src/components/menu/menu_item.js +++ b/packages/kbn-ui-framework/src/components/menu/menu_item.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/menu/menu_item.test.js b/packages/kbn-ui-framework/src/components/menu/menu_item.test.js index 1b08117b9c2b33..e06c1107778419 100644 --- a/packages/kbn-ui-framework/src/components/menu/menu_item.test.js +++ b/packages/kbn-ui-framework/src/components/menu/menu_item.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/modal/confirm_modal.js b/packages/kbn-ui-framework/src/components/modal/confirm_modal.js index b5ebb6c9f9e127..f6578231cec8f7 100644 --- a/packages/kbn-ui-framework/src/components/modal/confirm_modal.js +++ b/packages/kbn-ui-framework/src/components/modal/confirm_modal.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/modal/confirm_modal.test.js b/packages/kbn-ui-framework/src/components/modal/confirm_modal.test.js index 465cab35a7807f..ebad0489c7d419 100644 --- a/packages/kbn-ui-framework/src/components/modal/confirm_modal.test.js +++ b/packages/kbn-ui-framework/src/components/modal/confirm_modal.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import sinon from 'sinon'; import { mount, render } from 'enzyme'; diff --git a/packages/kbn-ui-framework/src/components/modal/index.js b/packages/kbn-ui-framework/src/components/modal/index.js index 9405ccebb17078..7ce9e7e38606be 100644 --- a/packages/kbn-ui-framework/src/components/modal/index.js +++ b/packages/kbn-ui-framework/src/components/modal/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiConfirmModal, CONFIRM_BUTTON as KUI_MODAL_CONFIRM_BUTTON, diff --git a/packages/kbn-ui-framework/src/components/modal/modal.js b/packages/kbn-ui-framework/src/components/modal/modal.js index a28762f4b457c5..0aa5d9ca504952 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal.js +++ b/packages/kbn-ui-framework/src/components/modal/modal.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal.test.js b/packages/kbn-ui-framework/src/components/modal/modal.test.js index fab4394b0c0605..0700079f590578 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal.test.js +++ b/packages/kbn-ui-framework/src/components/modal/modal.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal_body.js b/packages/kbn-ui-framework/src/components/modal/modal_body.js index e43d7ab5af189d..36bef25ae9b1b0 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal_body.js +++ b/packages/kbn-ui-framework/src/components/modal/modal_body.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import classnames from 'classnames'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal_body.test.js b/packages/kbn-ui-framework/src/components/modal/modal_body.test.js index 985b2cdb5a2b40..b2a70839a12acb 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal_body.test.js +++ b/packages/kbn-ui-framework/src/components/modal/modal_body.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal_footer.js b/packages/kbn-ui-framework/src/components/modal/modal_footer.js index b91240efe570d5..1ded35b7046e26 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal_footer.js +++ b/packages/kbn-ui-framework/src/components/modal/modal_footer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import classnames from 'classnames'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal_footer.test.js b/packages/kbn-ui-framework/src/components/modal/modal_footer.test.js index 9a54e5d8cae5ff..e8404292ce1e82 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal_footer.test.js +++ b/packages/kbn-ui-framework/src/components/modal/modal_footer.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal_header.js b/packages/kbn-ui-framework/src/components/modal/modal_header.js index 7aa74a1cff9f2c..9165e0c0a5b196 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal_header.js +++ b/packages/kbn-ui-framework/src/components/modal/modal_header.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import classnames from 'classnames'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal_header.test.js b/packages/kbn-ui-framework/src/components/modal/modal_header.test.js index f3a603bcb25674..10a51a1da4a8a9 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal_header.test.js +++ b/packages/kbn-ui-framework/src/components/modal/modal_header.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal_header_title.js b/packages/kbn-ui-framework/src/components/modal/modal_header_title.js index 5baa3bd0be1eb5..47d1960e02ae73 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal_header_title.js +++ b/packages/kbn-ui-framework/src/components/modal/modal_header_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import classnames from 'classnames'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal_header_title.test.js b/packages/kbn-ui-framework/src/components/modal/modal_header_title.test.js index 7f0632ad5b60b6..5ca29edfa97220 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal_header_title.test.js +++ b/packages/kbn-ui-framework/src/components/modal/modal_header_title.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal_overlay.js b/packages/kbn-ui-framework/src/components/modal/modal_overlay.js index 4467bdee3667fe..4d9ed64b8eadc9 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal_overlay.js +++ b/packages/kbn-ui-framework/src/components/modal/modal_overlay.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import classnames from 'classnames'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/modal/modal_overlay.test.js b/packages/kbn-ui-framework/src/components/modal/modal_overlay.test.js index 0600b5a45187a5..75c3feee14e3ca 100644 --- a/packages/kbn-ui-framework/src/components/modal/modal_overlay.test.js +++ b/packages/kbn-ui-framework/src/components/modal/modal_overlay.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/outside_click_detector/index.js b/packages/kbn-ui-framework/src/components/outside_click_detector/index.js index a05f19936044b4..52e22b67af175b 100644 --- a/packages/kbn-ui-framework/src/components/outside_click_detector/index.js +++ b/packages/kbn-ui-framework/src/components/outside_click_detector/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiOutsideClickDetector, } from './outside_click_detector'; diff --git a/packages/kbn-ui-framework/src/components/outside_click_detector/outside_click_detector.js b/packages/kbn-ui-framework/src/components/outside_click_detector/outside_click_detector.js index 7835dec70efdc1..0d107c24946744 100644 --- a/packages/kbn-ui-framework/src/components/outside_click_detector/outside_click_detector.js +++ b/packages/kbn-ui-framework/src/components/outside_click_detector/outside_click_detector.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Children, cloneElement, diff --git a/packages/kbn-ui-framework/src/components/outside_click_detector/outside_click_detector.test.js b/packages/kbn-ui-framework/src/components/outside_click_detector/outside_click_detector.test.js index 942abf51010bb3..5d872531f07bb6 100644 --- a/packages/kbn-ui-framework/src/components/outside_click_detector/outside_click_detector.test.js +++ b/packages/kbn-ui-framework/src/components/outside_click_detector/outside_click_detector.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; diff --git a/packages/kbn-ui-framework/src/components/pager/index.js b/packages/kbn-ui-framework/src/components/pager/index.js index 32d40130959e0e..bf59ee77b6f3d2 100644 --- a/packages/kbn-ui-framework/src/components/pager/index.js +++ b/packages/kbn-ui-framework/src/components/pager/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiPager } from './pager'; export { KuiPagerButtonGroup } from './pager_button_group'; diff --git a/packages/kbn-ui-framework/src/components/pager/pager.js b/packages/kbn-ui-framework/src/components/pager/pager.js index 76d44b6ac5d903..68dbc4053d601e 100644 --- a/packages/kbn-ui-framework/src/components/pager/pager.js +++ b/packages/kbn-ui-framework/src/components/pager/pager.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/pager/pager.test.js b/packages/kbn-ui-framework/src/components/pager/pager.test.js index 5ba7f528a97373..6a33af887458cc 100644 --- a/packages/kbn-ui-framework/src/components/pager/pager.test.js +++ b/packages/kbn-ui-framework/src/components/pager/pager.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import sinon from 'sinon'; import { render, mount } from 'enzyme'; diff --git a/packages/kbn-ui-framework/src/components/pager/pager_button_group.js b/packages/kbn-ui-framework/src/components/pager/pager_button_group.js index 4ddc4a250ffabb..826819742e9633 100644 --- a/packages/kbn-ui-framework/src/components/pager/pager_button_group.js +++ b/packages/kbn-ui-framework/src/components/pager/pager_button_group.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; diff --git a/packages/kbn-ui-framework/src/components/pager/pager_button_group.test.js b/packages/kbn-ui-framework/src/components/pager/pager_button_group.test.js index 29a0d4ebc1addb..f701f01cd0796e 100644 --- a/packages/kbn-ui-framework/src/components/pager/pager_button_group.test.js +++ b/packages/kbn-ui-framework/src/components/pager/pager_button_group.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import sinon from 'sinon'; import { render, mount } from 'enzyme'; diff --git a/packages/kbn-ui-framework/src/components/panel_simple/index.js b/packages/kbn-ui-framework/src/components/panel_simple/index.js index 2c948eca87c750..c9375a94888314 100644 --- a/packages/kbn-ui-framework/src/components/panel_simple/index.js +++ b/packages/kbn-ui-framework/src/components/panel_simple/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiPanelSimple, SIZES, diff --git a/packages/kbn-ui-framework/src/components/panel_simple/panel_simple.js b/packages/kbn-ui-framework/src/components/panel_simple/panel_simple.js index a7179538c5eb8a..8e902201ced0b5 100644 --- a/packages/kbn-ui-framework/src/components/panel_simple/panel_simple.js +++ b/packages/kbn-ui-framework/src/components/panel_simple/panel_simple.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/panel_simple/panel_simple.test.js b/packages/kbn-ui-framework/src/components/panel_simple/panel_simple.test.js index 8adfc8540fcd43..977011207a1601 100644 --- a/packages/kbn-ui-framework/src/components/panel_simple/panel_simple.test.js +++ b/packages/kbn-ui-framework/src/components/panel_simple/panel_simple.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/popover/index.js b/packages/kbn-ui-framework/src/components/popover/index.js index 8f3446fc6fdafe..397993ed3b9f48 100644 --- a/packages/kbn-ui-framework/src/components/popover/index.js +++ b/packages/kbn-ui-framework/src/components/popover/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiPopover, } from './popover'; export { KuiPopoverTitle } from './popover_title'; diff --git a/packages/kbn-ui-framework/src/components/popover/popover.js b/packages/kbn-ui-framework/src/components/popover/popover.js index 3b64fecf0fa9cb..46360ee869d43e 100644 --- a/packages/kbn-ui-framework/src/components/popover/popover.js +++ b/packages/kbn-ui-framework/src/components/popover/popover.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component, } from 'react'; diff --git a/packages/kbn-ui-framework/src/components/popover/popover.test.js b/packages/kbn-ui-framework/src/components/popover/popover.test.js index 103cda72500445..683fdaf0525c35 100644 --- a/packages/kbn-ui-framework/src/components/popover/popover.test.js +++ b/packages/kbn-ui-framework/src/components/popover/popover.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, mount } from 'enzyme'; import sinon from 'sinon'; diff --git a/packages/kbn-ui-framework/src/components/popover/popover_title.js b/packages/kbn-ui-framework/src/components/popover/popover_title.js index 7f20f924da7cd1..88aae95d400cdf 100644 --- a/packages/kbn-ui-framework/src/components/popover/popover_title.js +++ b/packages/kbn-ui-framework/src/components/popover/popover_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/popover/popover_title.test.js b/packages/kbn-ui-framework/src/components/popover/popover_title.test.js index e449e9f8d4e296..308afcfa97cac5 100644 --- a/packages/kbn-ui-framework/src/components/popover/popover_title.test.js +++ b/packages/kbn-ui-framework/src/components/popover/popover_title.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/table/controlled_table.js b/packages/kbn-ui-framework/src/components/table/controlled_table.js index 1882383bb02b93..bc6092e6f6f932 100644 --- a/packages/kbn-ui-framework/src/components/table/controlled_table.js +++ b/packages/kbn-ui-framework/src/components/table/controlled_table.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/table/controlled_table.test.js b/packages/kbn-ui-framework/src/components/table/controlled_table.test.js index 579549b85e2cd4..54582027d852b2 100644 --- a/packages/kbn-ui-framework/src/components/table/controlled_table.test.js +++ b/packages/kbn-ui-framework/src/components/table/controlled_table.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/table/index.js b/packages/kbn-ui-framework/src/components/table/index.js index 6687753a6b4a54..bc6b41f642ef7c 100644 --- a/packages/kbn-ui-framework/src/components/table/index.js +++ b/packages/kbn-ui-framework/src/components/table/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiTable } from './table'; export { KuiTableHeaderCell } from './table_header_cell'; export { KuiTableRow } from './table_row'; diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/__snapshots__/listing_table.test.js.snap b/packages/kbn-ui-framework/src/components/table/listing_table/__snapshots__/listing_table.test.js.snap index 8c101928651e36..513b1a0b1091ea 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/__snapshots__/listing_table.test.js.snap +++ b/packages/kbn-ui-framework/src/components/table/listing_table/__snapshots__/listing_table.test.js.snap @@ -21,6 +21,7 @@ exports[`renders KuiListingTable 1`] = ` class="kuiToolBarSearchBox__input" placeholder="Search..." type="text" + value="" /> @@ -41,7 +42,6 @@ exports[`renders KuiListingTable 1`] = ` aria-label="Select all rows" class="kuiCheckBox" type="checkbox" - value="on" /> @@ -81,7 +81,6 @@ exports[`renders KuiListingTable 1`] = ` aria-label="Select row" class="kuiCheckBox" type="checkbox" - value="on" /> @@ -117,7 +116,6 @@ exports[`renders KuiListingTable 1`] = ` aria-label="Select row" class="kuiCheckBox" type="checkbox" - value="on" /> @@ -153,7 +151,6 @@ exports[`renders KuiListingTable 1`] = ` aria-label="Select row" class="kuiCheckBox" type="checkbox" - value="on" /> diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/index.js b/packages/kbn-ui-framework/src/components/table/listing_table/index.js index b46f749cd8e9c3..0ad5ff0a93ab8f 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/index.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiListingTable } from './listing_table'; export { KuiListingTableCreateButton } from './listing_table_create_button'; export { KuiListingTableDeleteButton } from './listing_table_delete_button'; diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.js index c6733cefb7ef21..ad15d94b345c2a 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.test.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.test.js index 84a283527b9115..935670803e2b0a 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.test.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { mount, shallow } from 'enzyme'; import { requiredProps, takeMountedSnapshot } from '../../../test'; diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_create_button.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_create_button.js index 69ed7f8f8dbc39..5b06b2a9ef8d25 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_create_button.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_create_button.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_delete_button.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_delete_button.js index 2b9efae47352c6..07603a2df9345d 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_delete_button.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_delete_button.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_loading_prompt.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_loading_prompt.js index b5f5a2ac6ac086..af36ee4d4a1cfe 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_loading_prompt.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_loading_prompt.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_no_matches_prompt.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_no_matches_prompt.js index 20149f90e9ff21..5fd4cc27157e27 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_no_matches_prompt.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_no_matches_prompt.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_row.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_row.js index 0ee3a56e3f85a0..212ccfd7036371 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_row.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_row.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_tool_bar.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_tool_bar.js index f6d6699b5f21eb..c6659ee3063610 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_tool_bar.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_tool_bar.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_tool_bar_footer.js b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_tool_bar_footer.js index ab06cf8bedbd41..9cf191b0881cbe 100644 --- a/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_tool_bar_footer.js +++ b/packages/kbn-ui-framework/src/components/table/listing_table/listing_table_tool_bar_footer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/table/table.js b/packages/kbn-ui-framework/src/components/table/table.js index 3ebc63891d8b9a..62c7218aa4fb49 100644 --- a/packages/kbn-ui-framework/src/components/table/table.js +++ b/packages/kbn-ui-framework/src/components/table/table.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/table/table.test.js b/packages/kbn-ui-framework/src/components/table/table.test.js index 4a384bef135474..e20e0c33b3393e 100644 --- a/packages/kbn-ui-framework/src/components/table/table.test.js +++ b/packages/kbn-ui-framework/src/components/table/table.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/table/table_body.js b/packages/kbn-ui-framework/src/components/table/table_body.js index 79c8b285b761ad..c5fddbeeb9f2df 100644 --- a/packages/kbn-ui-framework/src/components/table/table_body.js +++ b/packages/kbn-ui-framework/src/components/table/table_body.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/table/table_header.js b/packages/kbn-ui-framework/src/components/table/table_header.js index e48b2af7694aba..acf2146c6cb8bf 100644 --- a/packages/kbn-ui-framework/src/components/table/table_header.js +++ b/packages/kbn-ui-framework/src/components/table/table_header.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; diff --git a/packages/kbn-ui-framework/src/components/table/table_header_cell.js b/packages/kbn-ui-framework/src/components/table/table_header_cell.js index 86feaea011d5e8..ae5861a90bcb6b 100644 --- a/packages/kbn-ui-framework/src/components/table/table_header_cell.js +++ b/packages/kbn-ui-framework/src/components/table/table_header_cell.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/table/table_header_cell.test.js b/packages/kbn-ui-framework/src/components/table/table_header_cell.test.js index 44e52ace914882..7e018b76ff4abf 100644 --- a/packages/kbn-ui-framework/src/components/table/table_header_cell.test.js +++ b/packages/kbn-ui-framework/src/components/table/table_header_cell.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/table/table_header_check_box_cell.js b/packages/kbn-ui-framework/src/components/table/table_header_check_box_cell.js index dcbb24e387fb0a..e0c368ba342b27 100644 --- a/packages/kbn-ui-framework/src/components/table/table_header_check_box_cell.js +++ b/packages/kbn-ui-framework/src/components/table/table_header_check_box_cell.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/table/table_header_check_box_cell.test.js b/packages/kbn-ui-framework/src/components/table/table_header_check_box_cell.test.js index e998beabecb480..921f2a6bf1e143 100644 --- a/packages/kbn-ui-framework/src/components/table/table_header_check_box_cell.test.js +++ b/packages/kbn-ui-framework/src/components/table/table_header_check_box_cell.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/table/table_info.js b/packages/kbn-ui-framework/src/components/table/table_info.js index d5a6ca9cfc9e48..66c99889eb66f1 100644 --- a/packages/kbn-ui-framework/src/components/table/table_info.js +++ b/packages/kbn-ui-framework/src/components/table/table_info.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/table/table_info.test.js b/packages/kbn-ui-framework/src/components/table/table_info.test.js index 4c5eb34c7265e0..0cd4625bec78df 100644 --- a/packages/kbn-ui-framework/src/components/table/table_info.test.js +++ b/packages/kbn-ui-framework/src/components/table/table_info.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/table/table_row.js b/packages/kbn-ui-framework/src/components/table/table_row.js index 56dc48507245ab..6d46c11026369c 100644 --- a/packages/kbn-ui-framework/src/components/table/table_row.js +++ b/packages/kbn-ui-framework/src/components/table/table_row.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/table/table_row.test.js b/packages/kbn-ui-framework/src/components/table/table_row.test.js index abc210710418c7..57ef1a86afdb19 100644 --- a/packages/kbn-ui-framework/src/components/table/table_row.test.js +++ b/packages/kbn-ui-framework/src/components/table/table_row.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/table/table_row_cell.js b/packages/kbn-ui-framework/src/components/table/table_row_cell.js index 180cb28736bf85..4b950c459d2708 100644 --- a/packages/kbn-ui-framework/src/components/table/table_row_cell.js +++ b/packages/kbn-ui-framework/src/components/table/table_row_cell.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/table/table_row_cell.test.js b/packages/kbn-ui-framework/src/components/table/table_row_cell.test.js index 117a3e8ef1336b..a2379a7474529f 100644 --- a/packages/kbn-ui-framework/src/components/table/table_row_cell.test.js +++ b/packages/kbn-ui-framework/src/components/table/table_row_cell.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/table/table_row_check_box_cell.js b/packages/kbn-ui-framework/src/components/table/table_row_check_box_cell.js index ee74e6d8f6a0b2..307e3f10e0a9e9 100644 --- a/packages/kbn-ui-framework/src/components/table/table_row_check_box_cell.js +++ b/packages/kbn-ui-framework/src/components/table/table_row_check_box_cell.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/table/table_row_check_box_cell.test.js b/packages/kbn-ui-framework/src/components/table/table_row_check_box_cell.test.js index 3429b36fcf3850..acd533f3df88a8 100644 --- a/packages/kbn-ui-framework/src/components/table/table_row_check_box_cell.test.js +++ b/packages/kbn-ui-framework/src/components/table/table_row_check_box_cell.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/tabs/index.js b/packages/kbn-ui-framework/src/components/tabs/index.js index 2c851311cb8665..c068bb4c354ddb 100644 --- a/packages/kbn-ui-framework/src/components/tabs/index.js +++ b/packages/kbn-ui-framework/src/components/tabs/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiTabs } from './tabs'; export { KuiTab } from './tab'; diff --git a/packages/kbn-ui-framework/src/components/tabs/tab.js b/packages/kbn-ui-framework/src/components/tabs/tab.js index d9da416fcee6a2..e7596a47dcc6f8 100644 --- a/packages/kbn-ui-framework/src/components/tabs/tab.js +++ b/packages/kbn-ui-framework/src/components/tabs/tab.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/tabs/tab.test.js b/packages/kbn-ui-framework/src/components/tabs/tab.test.js index 66311c4f90b8ec..396548c60f0b3c 100644 --- a/packages/kbn-ui-framework/src/components/tabs/tab.test.js +++ b/packages/kbn-ui-framework/src/components/tabs/tab.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, shallow } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/tabs/tabs.js b/packages/kbn-ui-framework/src/components/tabs/tabs.js index 98734e4738d43e..123ab136ee5b63 100644 --- a/packages/kbn-ui-framework/src/components/tabs/tabs.js +++ b/packages/kbn-ui-framework/src/components/tabs/tabs.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/tabs/tabs.test.js b/packages/kbn-ui-framework/src/components/tabs/tabs.test.js index 947bd1394da440..2242e060a17b1e 100644 --- a/packages/kbn-ui-framework/src/components/tabs/tabs.test.js +++ b/packages/kbn-ui-framework/src/components/tabs/tabs.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/index.js b/packages/kbn-ui-framework/src/components/tool_bar/index.js index f67c14de362d38..506a6dac37690e 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/index.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KuiToolBarSearchBox } from './tool_bar_search_box'; export { KuiToolBar } from './tool_bar'; export { KuiToolBarFooter } from './tool_bar_footer'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar.js index c25e7a150c258f..253391ace66993 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar.test.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar.test.js index bb6d7455736834..b9462d759e7a67 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar.test.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer.js index deea0206cd2d6a..b8b71968d4df40 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer.test.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer.test.js index 67c5d6132115e2..3ceba872d54e25 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer.test.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer_section.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer_section.js index 408252296aa6e3..c4ff90780f6caa 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer_section.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer_section.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer_section.test.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer_section.test.js index f41d6566cb75e8..3ded93ac3a5a26 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer_section.test.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_footer_section.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_search_box.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_search_box.js index 39d7be5bca77f6..e3f21d119163e5 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_search_box.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_search_box.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_search_box.test.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_search_box.test.js index 7f54bb3bb4e69d..745c085d4ca518 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_search_box.test.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_search_box.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, mount } from 'enzyme'; import sinon from 'sinon'; @@ -7,7 +26,7 @@ import { KuiToolBarSearchBox, } from './tool_bar_search_box'; -const onFilter = sinon.spy(); +const onFilter = sinon.stub(); test('renders KuiToolBarSearchBox', () => { const component = ; @@ -17,7 +36,7 @@ test('renders KuiToolBarSearchBox', () => { describe('onFilter', () => { test('is called on change event, with the value entered', () => { const searchBox = mount(); - onFilter.reset(); + onFilter.resetHistory(); const event = { target: { value: 'a' } }; searchBox.find('input').simulate('change', event); sinon.assert.calledWith(onFilter, 'a'); diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_section.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_section.js index 9eccdd1a0091c5..ad890e1ee7881c 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_section.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_section.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_section.test.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_section.test.js index 7a98f905d9c227..8446afadeed080 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_section.test.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_section.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_text.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_text.js index 6194bd53d9332d..517d4cd35d1db5 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_text.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_text.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_text.test.js b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_text.test.js index b55b49b2be8935..7ac6c7ce08962e 100644 --- a/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_text.test.js +++ b/packages/kbn-ui-framework/src/components/tool_bar/tool_bar_text.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/components/typography/typography.js b/packages/kbn-ui-framework/src/components/typography/typography.js index de4cedd6b2c752..b732d132432c3f 100644 --- a/packages/kbn-ui-framework/src/components/typography/typography.js +++ b/packages/kbn-ui-framework/src/components/typography/typography.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import { cloneElement } from 'react'; import classNames from 'classnames'; diff --git a/packages/kbn-ui-framework/src/components/typography/typography.test.js b/packages/kbn-ui-framework/src/components/typography/typography.test.js index d0fd054cba8730..626b84ef2c8a01 100644 --- a/packages/kbn-ui-framework/src/components/typography/typography.test.js +++ b/packages/kbn-ui-framework/src/components/typography/typography.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render } from 'enzyme'; import { requiredProps } from '../../test/required_props'; diff --git a/packages/kbn-ui-framework/src/services/accessibility/accessible_click_keys.js b/packages/kbn-ui-framework/src/services/accessibility/accessible_click_keys.js index 345df7d16788a5..c806bbf1d6b4ac 100644 --- a/packages/kbn-ui-framework/src/services/accessibility/accessible_click_keys.js +++ b/packages/kbn-ui-framework/src/services/accessibility/accessible_click_keys.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { ENTER, SPACE } from '../key_codes'; // These keys are used to execute click actions on interactive elements like buttons and links. diff --git a/packages/kbn-ui-framework/src/services/accessibility/cascading_menu_key_codes.js b/packages/kbn-ui-framework/src/services/accessibility/cascading_menu_key_codes.js index 95d5d566653c49..66f2c2609e7c63 100644 --- a/packages/kbn-ui-framework/src/services/accessibility/cascading_menu_key_codes.js +++ b/packages/kbn-ui-framework/src/services/accessibility/cascading_menu_key_codes.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * These keys are used for navigating cascading menu UI components. * diff --git a/packages/kbn-ui-framework/src/services/accessibility/combo_box_key_codes.js b/packages/kbn-ui-framework/src/services/accessibility/combo_box_key_codes.js index 844c105ac29eb5..c0d2bdfc54e079 100644 --- a/packages/kbn-ui-framework/src/services/accessibility/combo_box_key_codes.js +++ b/packages/kbn-ui-framework/src/services/accessibility/combo_box_key_codes.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * These keys are used for navigating combobox UI components. * diff --git a/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.js b/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.js index 8a78aa75d0bd7a..164910341f027b 100644 --- a/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.js +++ b/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import uuid from 'uuid'; /** diff --git a/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.test.js b/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.test.js index 0b46fdd6bf5725..85217273d34dc2 100644 --- a/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.test.js +++ b/packages/kbn-ui-framework/src/services/accessibility/html_id_generator.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { htmlIdGenerator } from './html_id_generator'; describe('htmlIdGenerator', () => { diff --git a/packages/kbn-ui-framework/src/services/accessibility/index.js b/packages/kbn-ui-framework/src/services/accessibility/index.js index b6e1a3c81b86c4..4eb4979d9d6eab 100644 --- a/packages/kbn-ui-framework/src/services/accessibility/index.js +++ b/packages/kbn-ui-framework/src/services/accessibility/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { accessibleClickKeys } from './accessible_click_keys'; export { cascadingMenuKeyCodes } from './cascading_menu_key_codes'; export { comboBoxKeyCodes } from './combo_box_key_codes'; diff --git a/packages/kbn-ui-framework/src/services/alignment.js b/packages/kbn-ui-framework/src/services/alignment.js index 0143613f196991..b2930bbf5b3032 100644 --- a/packages/kbn-ui-framework/src/services/alignment.js +++ b/packages/kbn-ui-framework/src/services/alignment.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const LEFT_ALIGNMENT = 'left'; export const RIGHT_ALIGNMENT = 'right'; diff --git a/packages/kbn-ui-framework/src/services/index.js b/packages/kbn-ui-framework/src/services/index.js index 579fcad53c9f15..6ed31a117e815c 100644 --- a/packages/kbn-ui-framework/src/services/index.js +++ b/packages/kbn-ui-framework/src/services/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // Export all keyCodes under a `keyCodes` named variable import * as keyCodes from './key_codes'; export { keyCodes }; diff --git a/packages/kbn-ui-framework/src/services/key_codes.js b/packages/kbn-ui-framework/src/services/key_codes.js index a5de66fd5999a6..6887844ebcff91 100644 --- a/packages/kbn-ui-framework/src/services/key_codes.js +++ b/packages/kbn-ui-framework/src/services/key_codes.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENTER = 13; export const SPACE = 32; export const ESCAPE = 27; diff --git a/packages/kbn-ui-framework/src/services/sort/index.js b/packages/kbn-ui-framework/src/services/sort/index.js index d945c274adff3a..57f2124c173558 100644 --- a/packages/kbn-ui-framework/src/services/sort/index.js +++ b/packages/kbn-ui-framework/src/services/sort/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { SortableProperties } from './sortable_properties'; diff --git a/packages/kbn-ui-framework/src/services/sort/sortable_properties.js b/packages/kbn-ui-framework/src/services/sort/sortable_properties.js index f5069827dcb460..db5a9a586e7b92 100644 --- a/packages/kbn-ui-framework/src/services/sort/sortable_properties.js +++ b/packages/kbn-ui-framework/src/services/sort/sortable_properties.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; /** diff --git a/packages/kbn-ui-framework/src/services/sort/sortable_properties.test.js b/packages/kbn-ui-framework/src/services/sort/sortable_properties.test.js index e0f4bb2b21b7e4..66c0fb0a60802c 100644 --- a/packages/kbn-ui-framework/src/services/sort/sortable_properties.test.js +++ b/packages/kbn-ui-framework/src/services/sort/sortable_properties.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { SortableProperties, } from './sortable_properties'; diff --git a/packages/kbn-ui-framework/src/test/find_test_subject.js b/packages/kbn-ui-framework/src/test/find_test_subject.js index 9dacbf3d17071e..046f954f118f3f 100644 --- a/packages/kbn-ui-framework/src/test/find_test_subject.js +++ b/packages/kbn-ui-framework/src/test/find_test_subject.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Find node which matches a specific test subject selector. Returns ReactWrappers around DOM element, * https://github.com/airbnb/enzyme/tree/master/docs/api/ReactWrapper. diff --git a/packages/kbn-ui-framework/src/test/index.js b/packages/kbn-ui-framework/src/test/index.js index 02a0977d7b0870..768f9052608a56 100644 --- a/packages/kbn-ui-framework/src/test/index.js +++ b/packages/kbn-ui-framework/src/test/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { requiredProps } from './required_props'; export { takeMountedSnapshot } from './take_mounted_snapshot'; export { findTestSubject } from './find_test_subject'; diff --git a/packages/kbn-ui-framework/src/test/required_props.js b/packages/kbn-ui-framework/src/test/required_props.js index 1d991b3d81e0d7..fc996680ed50ef 100644 --- a/packages/kbn-ui-framework/src/test/required_props.js +++ b/packages/kbn-ui-framework/src/test/required_props.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // We expect all React components to be able to support these props, // which will be rendered as HTML attributes. export const requiredProps = { diff --git a/packages/kbn-ui-framework/src/test/take_mounted_snapshot.js b/packages/kbn-ui-framework/src/test/take_mounted_snapshot.js index b043377e10ce16..4d87930d434b5f 100644 --- a/packages/kbn-ui-framework/src/test/take_mounted_snapshot.js +++ b/packages/kbn-ui-framework/src/test/take_mounted_snapshot.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Use this function to generate a Jest snapshot of components that have been fully rendered * using Enzyme's `mount` method. Typically, a mounted component will result in a snapshot diff --git a/packages/kbn-ui-framework/yarn.lock b/packages/kbn-ui-framework/yarn.lock index a26924373babb4..e3bd267f93b4eb 100644 --- a/packages/kbn-ui-framework/yarn.lock +++ b/packages/kbn-ui-framework/yarn.lock @@ -27,6 +27,12 @@ version "0.0.0" uid "" +"@sinonjs/formatio@^2.0.0": + version "2.0.0" + resolved "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" + dependencies: + samsam "1.3.0" + "@zeit/check-updates@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@zeit/check-updates/-/check-updates-1.1.0.tgz#d0f65026a36f27cd1fd54c647d8294447c1d2d8b" @@ -2085,7 +2091,7 @@ diff@^2.1.2: version "2.2.3" resolved "https://registry.yarnpkg.com/diff/-/diff-2.2.3.tgz#60eafd0d28ee906e4e8ff0a52c1229521033bf99" -diff@^3.3.1: +diff@^3.1.0, diff@^3.3.1: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -2773,12 +2779,6 @@ form-data@~2.3.1: combined-stream "1.0.6" mime-types "^2.1.12" -formatio@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" - dependencies: - samsam "~1.1" - forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -4027,6 +4027,10 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +just-extend@^1.1.27: + version "1.1.27" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" + keymirror@0.1.1, keymirror@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/keymirror/-/keymirror-0.1.1.tgz#918889ea13f8d0a42e7c557250eee713adc95c35" @@ -4215,9 +4219,9 @@ loglevel@^1.4.1: version "1.6.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" -lolex@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" +lolex@^2.2.0, lolex@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.5.0.tgz#69d6a667607738564daf108f63240ae8cbd28fb4" longest@^1.0.1: version "1.0.1" @@ -4562,6 +4566,16 @@ neo-async@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.0.tgz#76b1c823130cca26acfbaccc8fbaf0a2fa33b18f" +nise@^1.2.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.3.3.tgz#c17a850066a8a1dfeb37f921da02441afc4a82ba" + dependencies: + "@sinonjs/formatio" "^2.0.0" + just-extend "^1.1.27" + lolex "^2.3.2" + path-to-regexp "^1.7.0" + text-encoding "^0.6.4" + no-case@^2.2.0: version "2.3.2" resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" @@ -6089,13 +6103,9 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -samsam@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" - -samsam@~1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621" +samsam@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" sass-graph@^2.1.1: version "2.2.4" @@ -6341,14 +6351,17 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -sinon@1.17.2: - version "1.17.2" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.2.tgz#c1ea67b84a1e7b3350f6c4713efacef8e4ae8b71" +sinon@^5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-5.0.7.tgz#3bded6a73613ccc9e512e20246ced69a27c27dab" dependencies: - formatio "1.1.1" - lolex "1.3.2" - samsam "1.1.2" - util ">=0.10.3 <1" + "@sinonjs/formatio" "^2.0.0" + diff "^3.1.0" + lodash.get "^4.4.2" + lolex "^2.2.0" + nise "^1.2.0" + supports-color "^5.1.0" + type-detect "^4.0.5" slash@^1.0.0: version "1.0.0" @@ -6709,6 +6722,12 @@ supports-color@^4.0.0, supports-color@^4.2.1: dependencies: has-flag "^2.0.0" +supports-color@^5.1.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + supports-color@^5.2.0, supports-color@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" @@ -6788,6 +6807,10 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" +text-encoding@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -6918,6 +6941,10 @@ twig@^0.8.2: minimatch "3.0.x" walk "2.3.x" +type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + type-is@~1.6.15: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" @@ -7109,7 +7136,7 @@ util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -util@0.10.3, "util@>=0.10.3 <1", util@^0.10.3: +util@0.10.3, util@^0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" dependencies: diff --git a/preinstall_check.js b/preinstall_check.js index efbbf07372c96a..458c42d851dc3d 100644 --- a/preinstall_check.js +++ b/preinstall_check.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const isUsingNpm = process.env.npm_config_git !== undefined; if (isUsingNpm) { diff --git a/scripts/README.md b/scripts/README.md index 6ce2fdace69620..f41254dc380d96 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,4 +1,4 @@ -# kibana dev scripts +# Kibana Dev Scripts This directory contains scripts useful for interacting with Kibana tools in development. Use the node executable and `--help` flag to learn about how they work: @@ -6,11 +6,37 @@ This directory contains scripts useful for interacting with Kibana tools in deve node scripts/{{script name}} --help ``` -## for developers +## For Developers This directory is excluded from the build and tools within it should help users discover their capabilities. Each script in this directory must: -- require `src/babel-register` to bootstrap babel -- call out to source code that is in the `src` directory +- require `src/setup_node_env` to bootstrap NodeJS environment +- call out to source code in the [`src`](../src) or [`packages`](../packages) directories - react to the `--help` flag -- run everywhere OR check and fail fast when a required OS or toolchain is not available \ No newline at end of file +- run everywhere OR check and fail fast when a required OS or toolchain is not available + +## Functional Test Scripts + +**`node scripts/functional_tests [--config test/functional/config.js --config test/api_integration/config.js]`** + +Runs all the functional tests: selenium tests and api integration tests. List configs with multiple `--config` arguments. Uses the [@kbn/test](../packages/kbn-test) library to run Elasticsearch and Kibana servers and tests against those servers, for multiple server+test setups. In particular, calls out to [`runTests()`](../packages/kbn-test/src/functional_tests/tasks.js). Can be run on a single config. + +**`node scripts/functional_tests_server [--config test/functional/config.js]`** + +Starts just the Elasticsearch and Kibana servers given a single config, i.e. via `--config test/functional/config.js` or `--config test/api_integration/config`. Allows the user to start just the servers with this script, and keep them running while running tests against these servers. The idea is that the same config file configures both Elasticsearch and Kibana servers. Uses the [`startServers()`](../packages/kbn-test/src/functional_tests/tasks.js#L52-L80) method from [@kbn/test](../packages/kbn-test) library. + +Example. Start servers _and_ run tests, separately, but using the same config: + +```sh +# Just the servers +node scripts/functional_tests_server --config path/to/config +``` + +In another terminal: + +```sh +# Just the tests--against the running servers +node scripts/functional_test_runner --config path/to/config +``` + +For details on how the internal methods work, [read this readme](../packages/kbn-test/README.md). diff --git a/scripts/backport.js b/scripts/backport.js index 52546548ae8af1..64cd5721834ead 100755 --- a/scripts/backport.js +++ b/scripts/backport.js @@ -1 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env/node_version_validator'); require('backport'); diff --git a/scripts/build.js b/scripts/build.js index b669642d52ab77..dfd8287650e8a0 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('../src/dev/build/cli'); diff --git a/scripts/check_file_casing.js b/scripts/check_file_casing.js new file mode 100644 index 00000000000000..e35e5c7838d087 --- /dev/null +++ b/scripts/check_file_casing.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); +require('../src/dev/run_check_file_casing'); diff --git a/scripts/docs.js b/scripts/docs.js index 7d7d262c6c8a74..5f917f5fafe230 100644 --- a/scripts/docs.js +++ b/scripts/docs.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('../src/docs/cli'); diff --git a/scripts/es.js b/scripts/es.js index 6f1f37211896a0..26e8ed5f7f6918 100644 --- a/scripts/es.js +++ b/scripts/es.js @@ -1,16 +1,37 @@ -const path = require('path'); -const pkg = require('../package.json'); -const kbnEs = require('@kbn/es'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +var resolve = require('path').resolve; +var pkg = require('../package.json'); +var kbnEs = require('@kbn/es'); + +require('../src/setup_node_env'); kbnEs .run({ - license: 'trial', + license: 'basic', password: 'changeme', version: pkg.version, - 'source-path': path.resolve(__dirname, '../../elasticsearch'), - 'base-path': path.resolve(__dirname, '../.es'), + 'source-path': resolve(__dirname, '../../elasticsearch'), + 'base-path': resolve(__dirname, '../.es'), }) - .catch(e => { + .catch(function (e) { console.error(e); process.exitCode = 1; }); diff --git a/scripts/es_archiver.js b/scripts/es_archiver.js index 7b8674fbb33b61..faa8d9131240d0 100755 --- a/scripts/es_archiver.js +++ b/scripts/es_archiver.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('../src/es_archiver/cli'); diff --git a/scripts/eslint.js b/scripts/eslint.js index e517abad2ca602..fd3b3f259a9984 100644 --- a/scripts/eslint.js +++ b/scripts/eslint.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('../src/dev/run_eslint'); diff --git a/scripts/functional_test_runner.js b/scripts/functional_test_runner.js index 003b50d58f7820..6b298e9b30317e 100644 --- a/scripts/functional_test_runner.js +++ b/scripts/functional_test_runner.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('../src/functional_test_runner/cli'); diff --git a/scripts/functional_tests.js b/scripts/functional_tests.js new file mode 100644 index 00000000000000..75e4eab07ac06c --- /dev/null +++ b/scripts/functional_tests.js @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); +require('../packages/kbn-test').runTestsCli([ + require.resolve('../test/functional/config.js'), + require.resolve('../test/api_integration/config.js'), +]); diff --git a/scripts/functional_tests_server.js b/scripts/functional_tests_server.js new file mode 100644 index 00000000000000..156da2dfbbe1b5 --- /dev/null +++ b/scripts/functional_tests_server.js @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); +require('../packages/kbn-test').startServersCli( + require.resolve('../test/functional/config.js'), +); diff --git a/scripts/generate_plugin.js b/scripts/generate_plugin.js index cb9f2c8cf1f6ab..e080afb183aa8a 100644 --- a/scripts/generate_plugin.js +++ b/scripts/generate_plugin.js @@ -1 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('@kbn/plugin-generator').run(process.argv.slice(2)); diff --git a/scripts/jest.js b/scripts/jest.js index c859142c92cf92..c252056de766ba 100755 --- a/scripts/jest.js +++ b/scripts/jest.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // # Run Jest tests // // All args will be forwarded directly to Jest, e.g. to watch tests run: @@ -10,8 +29,8 @@ // // See all cli options in https://facebook.github.io/jest/docs/cli.html -const { resolve } = require('path'); +var resolve = require('path').resolve; process.argv.push('--config', resolve(__dirname, '../src/dev/jest/config.js')); -require('../src/babel-register'); +require('../src/setup_node_env'); require('../src/dev/jest/cli'); diff --git a/scripts/jest_integration.js b/scripts/jest_integration.js index ddb26939b6fff3..5eafcca2176cff 100755 --- a/scripts/jest_integration.js +++ b/scripts/jest_integration.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // # Run Jest integration tests // // All args will be forwarded directly to Jest, e.g. to watch tests run: @@ -10,8 +29,8 @@ // // See all cli options in https://facebook.github.io/jest/docs/cli.html -const { resolve } = require('path'); +var resolve = require('path').resolve; process.argv.push('--config', resolve(__dirname, '../src/dev/jest/config.integration.js')); -require('../src/babel-register'); +require('../src/setup_node_env'); require('../src/dev/jest/cli'); diff --git a/scripts/kbn.js b/scripts/kbn.js index b4aa213f017df9..e3b13ccfea2444 100644 --- a/scripts/kbn.js +++ b/scripts/kbn.js @@ -1,2 +1,21 @@ -require('../packages/kbn-pm/cli'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +require('../src/setup_node_env/node_version_validator'); +require('../packages/kbn-pm/cli'); diff --git a/scripts/kibana.js b/scripts/kibana.js index c4c655c853c9ca..b1b470a37535fc 100644 --- a/scripts/kibana.js +++ b/scripts/kibana.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('../src/cli/cli'); diff --git a/scripts/kibana_keystore.js b/scripts/kibana_keystore.js index c4579dc06c0cf2..3efd3500e1f8ef 100644 --- a/scripts/kibana_keystore.js +++ b/scripts/kibana_keystore.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('../src/cli_keystore'); diff --git a/scripts/kibana_plugin.js b/scripts/kibana_plugin.js index 5bd1304a5e8a0f..2478e515297ef7 100644 --- a/scripts/kibana_plugin.js +++ b/scripts/kibana_plugin.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('../src/cli_plugin/cli'); diff --git a/scripts/makelogs.js b/scripts/makelogs.js index b1cc91bfb0e73e..55fc0fae4e1c48 100644 --- a/scripts/makelogs.js +++ b/scripts/makelogs.js @@ -1 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env/node_version_validator'); require('makelogs'); diff --git a/scripts/mocha.js b/scripts/mocha.js index 6dce353b705afb..e8d6c31d02ef29 100644 --- a/scripts/mocha.js +++ b/scripts/mocha.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); -require('../test/scripts/run_mocha'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); +require('../src/dev/mocha').runMochaCli(); diff --git a/scripts/notice.js b/scripts/notice.js index 2f8dda3ab13f51..a96417b6b608fa 100644 --- a/scripts/notice.js +++ b/scripts/notice.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('../src/dev/notice/cli'); diff --git a/scripts/precommit_hook.js b/scripts/precommit_hook.js index 857755567f522a..fecd950de3fbcc 100644 --- a/scripts/precommit_hook.js +++ b/scripts/precommit_hook.js @@ -1,2 +1,21 @@ -require('../src/babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); require('../src/dev/run_precommit_hook'); diff --git a/scripts/tslint.js b/scripts/tslint.js new file mode 100644 index 00000000000000..0ec8ce7dd632a3 --- /dev/null +++ b/scripts/tslint.js @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../src/setup_node_env'); +require('../src/dev/tslint').runTslintCli(); diff --git a/src/babel-register/index.js b/src/babel-register/index.js deleted file mode 100644 index d10546d1f98a99..00000000000000 --- a/src/babel-register/index.js +++ /dev/null @@ -1,5 +0,0 @@ -// register and polyfill need to happen in this -// order and in separate files. Checkout each file -// for a much more detailed explaination -require('./register'); -require('./polyfill'); diff --git a/src/babel-register/polyfill.js b/src/babel-register/polyfill.js deleted file mode 100644 index fedca3745ba87c..00000000000000 --- a/src/babel-register/polyfill.js +++ /dev/null @@ -1,10 +0,0 @@ -// `babel-preset-env` looks for and rewrites the following import -// statement into a list of import statements based on the polyfills -// necessary for our target environment (the current version of node) -// but since it does that during compilation, `import 'babel-polyfill'` -// must be in a file that is loaded with `require()` AFTER `babel-register` -// is configured. -// -// This is why we have this single statement in it's own file and require -// it from ./index.js -import 'babel-polyfill'; diff --git a/src/cli/cli.js b/src/cli/cli.js index ddfd862bca7b02..68cf8017ce3690 100644 --- a/src/cli/cli.js +++ b/src/cli/cli.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { pkg } from '../utils'; import Command from './command'; @@ -10,7 +29,7 @@ program .version(pkg.version) .description( 'Kibana is an open source (Apache Licensed), browser ' + - 'based analytics and search dashboard for Elasticsearch.' + 'based analytics and search dashboard for Elasticsearch.' ); // attach commands diff --git a/src/cli/cluster/_mock_cluster_fork.js b/src/cli/cluster/_mock_cluster_fork.js index 0915d172a4cd60..4312f6a85c53ad 100644 --- a/src/cli/cluster/_mock_cluster_fork.js +++ b/src/cli/cluster/_mock_cluster_fork.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import EventEmitter from 'events'; import { assign, random } from 'lodash'; import sinon from 'sinon'; diff --git a/src/cli/cluster/base_path_proxy.js b/src/cli/cluster/base_path_proxy.js index d13d87c243ab20..b6cd3f93b22493 100644 --- a/src/cli/cluster/base_path_proxy.js +++ b/src/cli/cluster/base_path_proxy.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Server } from 'hapi'; import { notFound } from 'boom'; import { map, sample } from 'lodash'; @@ -5,22 +24,17 @@ import { map as promiseMap, fromNode } from 'bluebird'; import { Agent as HttpsAgent } from 'https'; import { readFileSync } from 'fs'; -import { Config } from '../../server/config/config'; import { setupConnection } from '../../server/http/setup_connection'; import { registerHapiPlugins } from '../../server/http/register_hapi_plugins'; import { setupLogging } from '../../server/logging'; -import { transformDeprecations } from '../../server/config/transform_deprecations'; const alphabet = 'abcdefghijklmnopqrztuvwxyz'.split(''); export default class BasePathProxy { - constructor(clusterManager, userSettings) { + constructor(clusterManager, config) { this.clusterManager = clusterManager; this.server = new Server(); - const settings = transformDeprecations(userSettings); - const config = Config.withDefaultSchema(settings); - this.targetPort = config.get('dev.basePathProxyTarget'); this.basePath = config.get('server.basePath'); diff --git a/src/cli/cluster/cluster_manager.js b/src/cli/cluster/cluster_manager.js index 987bc26957927b..5ae5ca2bfadc64 100644 --- a/src/cli/cluster/cluster_manager.js +++ b/src/cli/cluster/cluster_manager.js @@ -1,16 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve } from 'path'; import { debounce, invoke, bindAll, once, uniq } from 'lodash'; import Log from '../log'; import Worker from './worker'; import BasePathProxy from './base_path_proxy'; +import { Config } from '../../server/config/config'; +import { transformDeprecations } from '../../server/config/transform_deprecations'; process.env.kbnWorkerType = 'managr'; export default class ClusterManager { - constructor(opts = {}, settings = {}) { + static async create(opts = {}, settings = {}) { + const transformedSettings = transformDeprecations(settings); + const config = await Config.withDefaultSchema(transformedSettings); + + return new ClusterManager(opts, config); + } + + constructor(opts, config) { this.log = new Log(opts.quiet, opts.silent); this.addedCount = 0; + this.inReplMode = !!opts.repl; const serverArgv = []; const optimizerArgv = [ @@ -19,7 +48,7 @@ export default class ClusterManager { ]; if (opts.basePath) { - this.basePathProxy = new BasePathProxy(this, settings); + this.basePathProxy = new BasePathProxy(this, config); optimizerArgv.push( `--server.basePath=${this.basePathProxy.basePath}`, @@ -63,14 +92,16 @@ export default class ClusterManager { bindAll(this, 'onWatcherAdd', 'onWatcherError', 'onWatcherChange'); if (opts.watch) { + const pluginPaths = config.get('plugins.paths'); + const scanDirs = config.get('plugins.scanDirs'); const extraPaths = [ - ...settings.plugins.paths, - ...settings.plugins.scanDirs, + ...pluginPaths, + ...scanDirs, ]; - const extraIgnores = settings.plugins.scanDirs + const extraIgnores = scanDirs .map(scanDir => resolve(scanDir, '*')) - .concat(settings.plugins.paths) + .concat(pluginPaths) .reduce((acc, path) => acc.concat( resolve(path, 'test'), resolve(path, 'build'), @@ -133,6 +164,12 @@ export default class ClusterManager { } setupManualRestart() { + // If we're in REPL mode, the user can use the REPL to manually restart. + // The setupManualRestart method interferes with stdin/stdout, in a way + // that negatively affects the REPL. + if (this.inReplMode) { + return; + } const readline = require('readline'); const rl = readline.createInterface(process.stdin, process.stdout); diff --git a/src/cli/cluster/cluster_manager.test.js b/src/cli/cluster/cluster_manager.test.js index 523a43818da3b0..b80ee62da29c31 100644 --- a/src/cli/cluster/cluster_manager.test.js +++ b/src/cli/cluster/cluster_manager.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import cluster from 'cluster'; import { sample } from 'lodash'; @@ -6,10 +25,10 @@ import ClusterManager from './cluster_manager'; import Worker from './worker'; describe('CLI cluster manager', function () { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); beforeEach(function () { - sandbox.stub(cluster, 'fork', function () { + sandbox.stub(cluster, 'fork').callsFake(() => { return { process: { kill: sinon.stub(), @@ -26,8 +45,8 @@ describe('CLI cluster manager', function () { sandbox.restore(); }); - it('has two workers', function () { - const manager = new ClusterManager({}); + it('has two workers', async function () { + const manager = await ClusterManager.create({}); expect(manager.workers).toHaveLength(2); for (const worker of manager.workers) expect(worker).toBeInstanceOf(Worker); @@ -36,8 +55,8 @@ describe('CLI cluster manager', function () { expect(manager.server).toBeInstanceOf(Worker); }); - it('delivers broadcast messages to other workers', function () { - const manager = new ClusterManager({}); + it('delivers broadcast messages to other workers', async function () { + const manager = await ClusterManager.create({}); for (const worker of manager.workers) { Worker.prototype.start.call(worker);// bypass the debounced start method diff --git a/src/cli/cluster/worker.js b/src/cli/cluster/worker.js index 73e545d7778db1..a7176bc0c734cb 100644 --- a/src/cli/cluster/worker.js +++ b/src/cli/cluster/worker.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import cluster from 'cluster'; import { EventEmitter } from 'events'; diff --git a/src/cli/cluster/worker.test.js b/src/cli/cluster/worker.test.js index 61a5b51909b15b..6577fe27260bb0 100644 --- a/src/cli/cluster/worker.test.js +++ b/src/cli/cluster/worker.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import cluster from 'cluster'; import { findIndex } from 'lodash'; @@ -32,10 +51,10 @@ function setup(opts = {}) { } describe('CLI cluster manager', function () { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); beforeEach(function () { - sandbox.stub(cluster, 'fork', () => new MockClusterFork()); + sandbox.stub(cluster, 'fork').callsFake(() => new MockClusterFork()); }); afterEach(async function () { diff --git a/src/cli/color.js b/src/cli/color.js index 99bb5f00be7f22..b678376ef7c247 100644 --- a/src/cli/color.js +++ b/src/cli/color.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import chalk from 'chalk'; diff --git a/src/cli/command.js b/src/cli/command.js index 476e3fd166d0ef..602b66436d6358 100644 --- a/src/cli/command.js +++ b/src/cli/command.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import help from './help'; diff --git a/src/cli/dev_ssl.js b/src/cli/dev_ssl.js index e9d35a2eceb8db..110f44ee57b7d7 100644 --- a/src/cli/dev_ssl.js +++ b/src/cli/dev_ssl.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve } from 'path'; export const DEV_SSL_CERT_PATH = resolve(__dirname, '../../test/dev_certs/server.crt'); export const DEV_SSL_KEY_PATH = resolve(__dirname, '../../test/dev_certs/server.key'); diff --git a/src/cli/help.js b/src/cli/help.js index d4ac26cb924849..30cf70669746a0 100644 --- a/src/cli/help.js +++ b/src/cli/help.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export default function help(command, spaces) { diff --git a/src/cli/index.js b/src/cli/index.js index d5b8a863770511..4af5e3c68423cd 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -1,2 +1,21 @@ -require('../babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../setup_node_env'); require('./cli'); diff --git a/src/cli/log.js b/src/cli/log.js index 3731d2c46a7f62..8deccc6f548655 100644 --- a/src/cli/log.js +++ b/src/cli/log.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; const log = _.restParam(function (color, label, rest1) { diff --git a/src/cli/repl/__snapshots__/repl.test.js.snap b/src/cli/repl/__snapshots__/repl.test.js.snap new file mode 100644 index 00000000000000..7171e99dbcc0eb --- /dev/null +++ b/src/cli/repl/__snapshots__/repl.test.js.snap @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`repl it allows print depth to be specified 1`] = `"{ '0': { '1': { '2': [Object] } }, whoops: [Circular] }"`; + +exports[`repl it colorizes raw values 1`] = `"{ meaning: 42 }"`; + +exports[`repl it handles deep and recursive objects 1`] = ` +"{ '0': { '1': { '2': { '3': { '4': { '5': [Object] } } } } }, + whoops: [Circular] }" +`; + +exports[`repl it handles undefined 1`] = `"undefined"`; + +exports[`repl it prints promise rejects 1`] = ` +Array [ + Array [ + "Waiting for promise...", + ], + Array [ + "Promise Rejected: +", + "'Dang, diggity!'", + ], +] +`; + +exports[`repl it prints promise resolves 1`] = ` +Array [ + Array [ + "Waiting for promise...", + ], + Array [ + "Promise Resolved: +", + "[ 1, 2, 3 ]", + ], +] +`; + +exports[`repl promises rejects only write to a specific depth 1`] = ` +Array [ + Array [ + "Waiting for promise...", + ], + Array [ + "Promise Rejected: +", + "{ '0': { '1': { '2': { '3': { '4': { '5': [Object] } } } } }, + whoops: [Circular] }", + ], +] +`; + +exports[`repl promises resolves only write to a specific depth 1`] = ` +Array [ + Array [ + "Waiting for promise...", + ], + Array [ + "Promise Resolved: +", + "{ '0': { '1': { '2': { '3': { '4': { '5': [Object] } } } } }, + whoops: [Circular] }", + ], +] +`; + +exports[`repl repl exposes a print object that lets you tailor depth 1`] = ` +Array [ + Array [ + "{ hello: { world: [Object] } }", + ], +] +`; + +exports[`repl repl exposes a print object that prints promises 1`] = ` +Array [ + Array [ + "", + ], + Array [ + "Waiting for promise...", + ], + Array [ + "Promise Resolved: +", + "{ hello: { world: [Object] } }", + ], +] +`; diff --git a/src/cli/repl/index.js b/src/cli/repl/index.js new file mode 100644 index 00000000000000..01d66d14d9ef44 --- /dev/null +++ b/src/cli/repl/index.js @@ -0,0 +1,86 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import repl from 'repl'; +import util from 'util'; + +const PRINT_DEPTH = 5; + +/** + * Starts an interactive REPL with a global `server` object. + * + * @param {KibanaServer} kbnServer + */ +export function startRepl(kbnServer) { + const replServer = repl.start({ + prompt: 'Kibana> ', + useColors: true, + writer: promiseFriendlyWriter({ + displayPrompt: () => replServer.displayPrompt(), + getPrintDepth: () => replServer.context.repl.printDepth, + }), + }); + + const initializeContext = () => { + replServer.context.kbnServer = kbnServer; + replServer.context.server = kbnServer.server; + replServer.context.repl = { + printDepth: PRINT_DEPTH, + print(obj, depth = null) { + console.log(promisePrint(obj, () => replServer.displayPrompt(), () => depth)); + return ''; + }, + }; + }; + + initializeContext(); + replServer.on('reset', initializeContext); + + return replServer; +} + +function colorize(o, depth) { + return util.inspect(o, { colors: true, depth }); +} + +function prettyPrint(text, o, depth) { + console.log(text, colorize(o, depth)); +} + +// This lets us handle promises more gracefully than the default REPL, +// which doesn't show the results. +function promiseFriendlyWriter({ displayPrompt, getPrintDepth }) { + return (result) => promisePrint(result, displayPrompt, getPrintDepth); +} + +function promisePrint(result, displayPrompt, getPrintDepth) { + const depth = getPrintDepth(); + if (result && typeof result.then === 'function') { + // Bit of a hack to encourage the user to wait for the result of a promise + // by printing text out beside the current prompt. + Promise.resolve() + .then(() => console.log('Waiting for promise...')) + .then(() => result) + .then((o) => prettyPrint('Promise Resolved: \n', o, depth)) + .catch((err) => prettyPrint('Promise Rejected: \n', err, depth)) + .then(displayPrompt); + return ''; + } + return colorize(result, depth); +} diff --git a/src/cli/repl/repl.test.js b/src/cli/repl/repl.test.js new file mode 100644 index 00000000000000..77e4020bf4b663 --- /dev/null +++ b/src/cli/repl/repl.test.js @@ -0,0 +1,216 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +jest.mock('repl', () => ({ start: (opts) => ({ opts, context: {} }) }), { virtual: true }); + +describe('repl', () => { + const originalConsoleLog = console.log; + let mockRepl; + + beforeEach(() => { + global.console.log = jest.fn(); + require('repl').start = (opts) => { + let resetHandler; + const replServer = { + opts, + context: { }, + on: jest.fn((eventName, handler) => { + expect(eventName).toBe('reset'); + resetHandler = handler; + }), + }; + + mockRepl = { + replServer, + clear() { + replServer.context = {}; + resetHandler(replServer.context); + }, + }; + return replServer; + }; + }); + + afterEach(() => { + global.console.log = originalConsoleLog; + }); + + test('it exposes the server object', () => { + const { startRepl } = require('.'); + const testServer = { + server: { }, + }; + const replServer = startRepl(testServer); + expect(replServer.context.server).toBe(testServer.server); + expect(replServer.context.kbnServer).toBe(testServer); + }); + + test('it prompts with Kibana>', () => { + const { startRepl } = require('.'); + expect(startRepl({}).opts.prompt).toBe('Kibana> '); + }); + + test('it colorizes raw values', () => { + const { startRepl } = require('.'); + const replServer = startRepl({}); + expect(replServer.opts.writer({ meaning: 42 })) + .toMatchSnapshot(); + }); + + test('it handles undefined', () => { + const { startRepl } = require('.'); + const replServer = startRepl({}); + expect(replServer.opts.writer()) + .toMatchSnapshot(); + }); + + test('it handles deep and recursive objects', () => { + const { startRepl } = require('.'); + const replServer = startRepl({}); + const splosion = {}; + let child = splosion; + for (let i = 0; i < 2000; ++i) { + child[i] = {}; + child = child[i]; + } + splosion.whoops = splosion; + expect(replServer.opts.writer(splosion)) + .toMatchSnapshot(); + }); + + test('it allows print depth to be specified', () => { + const { startRepl } = require('.'); + const replServer = startRepl({}); + const splosion = {}; + let child = splosion; + for (let i = 0; i < 2000; ++i) { + child[i] = {}; + child = child[i]; + } + splosion.whoops = splosion; + replServer.context.repl.printDepth = 2; + expect(replServer.opts.writer(splosion)) + .toMatchSnapshot(); + }); + + test('resets context to original when reset', () => { + const { startRepl } = require('.'); + const testServer = { + server: { }, + }; + const replServer = startRepl(testServer); + replServer.context.foo = 'bar'; + expect(replServer.context.server).toBe(testServer.server); + expect(replServer.context.kbnServer).toBe(testServer); + expect(replServer.context.foo).toBe('bar'); + mockRepl.clear(); + expect(replServer.context.server).toBe(testServer.server); + expect(replServer.context.kbnServer).toBe(testServer); + expect(replServer.context.foo).toBeUndefined(); + }); + + test('it prints promise resolves', async () => { + const { startRepl } = require('.'); + const replServer = startRepl({}); + const calls = await waitForPrompt( + replServer, + () => replServer.opts.writer(Promise.resolve([1, 2, 3])), + ); + expect(calls) + .toMatchSnapshot(); + }); + + test('it prints promise rejects', async () => { + const { startRepl } = require('.'); + const replServer = startRepl({}); + const calls = await waitForPrompt( + replServer, + () => replServer.opts.writer(Promise.reject('Dang, diggity!')), + ); + expect(calls) + .toMatchSnapshot(); + }); + + test('promises resolves only write to a specific depth', async () => { + const { startRepl } = require('.'); + const replServer = startRepl({}); + const splosion = {}; + let child = splosion; + for (let i = 0; i < 2000; ++i) { + child[i] = {}; + child = child[i]; + } + splosion.whoops = splosion; + const calls = await waitForPrompt( + replServer, + () => replServer.opts.writer(Promise.resolve(splosion)), + ); + expect(calls) + .toMatchSnapshot(); + }); + + test('promises rejects only write to a specific depth', async () => { + const { startRepl } = require('.'); + const replServer = startRepl({}); + const splosion = {}; + let child = splosion; + for (let i = 0; i < 2000; ++i) { + child[i] = {}; + child = child[i]; + } + splosion.whoops = splosion; + const calls = await waitForPrompt( + replServer, + () => replServer.opts.writer(Promise.reject(splosion)), + ); + expect(calls) + .toMatchSnapshot(); + }); + + test('repl exposes a print object that lets you tailor depth', () => { + const { startRepl } = require('.'); + const replServer = startRepl({}); + replServer.context.repl.print({ hello: { world: { nstuff: 'yo' } } }, 1); + expect(global.console.log.mock.calls) + .toMatchSnapshot(); + }); + + test('repl exposes a print object that prints promises', async () => { + const { startRepl } = require('.'); + const replServer = startRepl({}); + const promise = Promise.resolve({ hello: { world: { nstuff: 'yo' } } }); + const calls = await waitForPrompt( + replServer, + () => replServer.context.repl.print(promise, 1), + ); + expect(calls) + .toMatchSnapshot(); + }); + + async function waitForPrompt(replServer, fn) { + let resolveDone; + const done = new Promise((resolve) => resolveDone = resolve); + replServer.displayPrompt = () => { + resolveDone(); + }; + fn(); + await done; + return global.console.log.mock.calls; + } +}); diff --git a/src/cli/serve/integration_tests/invalid_config.test.js b/src/cli/serve/integration_tests/invalid_config.test.js index 3fbf22abc80ac5..335fb1dbcaf9f6 100644 --- a/src/cli/serve/integration_tests/invalid_config.test.js +++ b/src/cli/serve/integration_tests/invalid_config.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { spawnSync } from 'child_process'; import { resolve } from 'path'; diff --git a/src/cli/serve/integration_tests/reload_logging_config.test.js b/src/cli/serve/integration_tests/reload_logging_config.test.js index a4898212ab2388..2d7d6664930dff 100644 --- a/src/cli/serve/integration_tests/reload_logging_config.test.js +++ b/src/cli/serve/integration_tests/reload_logging_config.test.js @@ -1,8 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { spawn } from 'child_process'; import { writeFileSync } from 'fs'; import { relative, resolve } from 'path'; import { safeDump } from 'js-yaml'; import es from 'event-stream'; +import stripAnsi from 'strip-ansi'; import { readYamlConfig } from '../read_yaml_config'; const testConfigFile = follow('__fixtures__/reload_logging_config/kibana.test.yml'); @@ -29,10 +49,10 @@ const prepareJson = obj => ({ }); const prepareLogLine = str => - str.replace( + stripAnsi(str.replace( /\[\d{2}:\d{2}:\d{2}.\d{3}\]/, '[## timestamp ##]' - ); + )); describe('Server logging configuration', function () { let child; diff --git a/src/cli/serve/read_keystore.js b/src/cli/serve/read_keystore.js index ecaa6e55deb290..672e41dcddab21 100644 --- a/src/cli/serve/read_keystore.js +++ b/src/cli/serve/read_keystore.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { join } from 'path'; import { set } from 'lodash'; diff --git a/src/cli/serve/read_yaml_config.js b/src/cli/serve/read_yaml_config.js index 55f7691c6b131a..f2ad397abf7c39 100644 --- a/src/cli/serve/read_yaml_config.js +++ b/src/cli/serve/read_yaml_config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { isArray, isPlainObject, forOwn, set, transform, isString } from 'lodash'; import { readFileSync as read } from 'fs'; import { safeLoad } from 'js-yaml'; diff --git a/src/cli/serve/read_yaml_config.test.js b/src/cli/serve/read_yaml_config.test.js index d0b99470e81505..09898a25c45b00 100644 --- a/src/cli/serve/read_yaml_config.test.js +++ b/src/cli/serve/read_yaml_config.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { relative, resolve } from 'path'; import { readYamlConfig } from './read_yaml_config'; diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index 3d27adb51cf5e9..e046438b6e3f04 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { statSync, lstatSync, realpathSync } from 'fs'; import { isWorker } from 'cluster'; @@ -10,6 +29,8 @@ import { readKeystore } from './read_keystore'; import { DEV_SSL_CERT_PATH, DEV_SSL_KEY_PATH } from '../dev_ssl'; +const { startRepl } = canRequire('../repl') ? require('../repl') : { }; + function canRequire(path) { try { require.resolve(path); @@ -152,6 +173,10 @@ export default function (program) { ) .option('--plugins ', 'an alias for --plugin-dir', pluginDirCollector); + if (!!startRepl) { + command.option('--repl', 'Run the server with a REPL prompt and access to the server object'); + } + if (XPACK_OPTIONAL) { command .option('--oss', 'Start Kibana without X-Pack'); @@ -184,7 +209,7 @@ export default function (program) { if (CAN_CLUSTER && opts.dev && !isWorker) { // stop processing the action and handoff to cluster manager const ClusterManager = require(CLUSTER_MANAGER_PATH); - new ClusterManager(opts, settings); + await ClusterManager.create(opts, settings); return; } @@ -192,6 +217,9 @@ export default function (program) { const KbnServer = require('../../server/kbn_server'); try { kbnServer = new KbnServer(settings); + if (shouldStartRepl(opts)) { + startRepl(kbnServer); + } await kbnServer.ready(); } catch (error) { const { server } = kbnServer; @@ -216,10 +244,10 @@ export default function (program) { process.exit(exitCode); } - process.on('SIGHUP', function reloadConfig() { + process.on('SIGHUP', async function reloadConfig() { const settings = getCurrentSettings(); kbnServer.server.log(['info', 'config'], 'Reloading logging configuration due to SIGHUP.'); - kbnServer.applyLoggingConfiguration(settings); + await kbnServer.applyLoggingConfiguration(settings); kbnServer.server.log(['info', 'config'], 'Reloaded logging configuration due to SIGHUP.'); }); @@ -227,6 +255,17 @@ export default function (program) { }); } +function shouldStartRepl(opts) { + if (opts.repl && !startRepl) { + throw new Error('Kibana REPL mode can only be run in development mode.'); + } + + // The kbnWorkerType check is necessary to prevent the repl + // from being started multiple times in different processes. + // We only want one REPL. + return opts.repl && process.env.kbnWorkerType === 'server'; +} + function logFatal(message, server) { if (server) { server.log(['fatal'], message); diff --git a/src/cli_keystore/add.js b/src/cli_keystore/add.js index 4d03d4be087a93..84441ae718ff60 100644 --- a/src/cli_keystore/add.js +++ b/src/cli_keystore/add.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Logger from '../cli_plugin/lib/logger'; import { confirm, question } from '../server/utils'; import { createPromiseFromStreams, createConcatStream } from '../utils'; diff --git a/src/cli_keystore/add.test.js b/src/cli_keystore/add.test.js index 3282a9d4e949e9..fdf6708cfd94de 100644 --- a/src/cli_keystore/add.test.js +++ b/src/cli_keystore/add.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import mockFs from 'mock-fs'; import { PassThrough } from 'stream'; @@ -9,7 +28,7 @@ import * as prompt from '../server/utils/prompt'; describe('Kibana keystore', () => { describe('add', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); const keystoreData = '1:IxR0geiUTMJp8ueHDkqeUJ0I9eEw4NJPXIJi22UDyfGfJSy4mH' + 'BBuGPkkAix/x/YFfIxo4tiKGdJ2oVTtU8LgKDkVoGdL+z7ylY4n3myatt6osqhI4lzJ9M' diff --git a/src/cli_keystore/cli_keystore.js b/src/cli_keystore/cli_keystore.js index 182168566051df..af67bf2638c670 100644 --- a/src/cli_keystore/cli_keystore.js +++ b/src/cli_keystore/cli_keystore.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { join } from 'path'; import { pkg } from '../utils'; diff --git a/src/cli_keystore/create.js b/src/cli_keystore/create.js index 1498dc4718fcf6..89a1a6e6d0bd1b 100644 --- a/src/cli_keystore/create.js +++ b/src/cli_keystore/create.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Logger from '../cli_plugin/lib/logger'; import { confirm } from '../server/utils'; diff --git a/src/cli_keystore/create.test.js b/src/cli_keystore/create.test.js index b1a04f9e09660a..234212b93a1ba4 100644 --- a/src/cli_keystore/create.test.js +++ b/src/cli_keystore/create.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import mockFs from 'mock-fs'; @@ -8,7 +27,7 @@ import * as prompt from '../server/utils/prompt'; describe('Kibana keystore', () => { describe('create', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); const keystoreData = '1:IxR0geiUTMJp8ueHDkqeUJ0I9eEw4NJPXIJi22UDyfGfJSy4mH' + 'BBuGPkkAix/x/YFfIxo4tiKGdJ2oVTtU8LgKDkVoGdL+z7ylY4n3myatt6osqhI4lzJ9M' diff --git a/src/cli_keystore/index.js b/src/cli_keystore/index.js index 9abdc46bc8f8ca..12dc51134aad77 100644 --- a/src/cli_keystore/index.js +++ b/src/cli_keystore/index.js @@ -1,2 +1,21 @@ -require('../babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../setup_node_env'); require('./cli_keystore'); diff --git a/src/cli_keystore/list.js b/src/cli_keystore/list.js index dac772ae43e048..3a0622f9486236 100644 --- a/src/cli_keystore/list.js +++ b/src/cli_keystore/list.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Logger from '../cli_plugin/lib/logger'; export function list(keystore, command, options = {}) { diff --git a/src/cli_keystore/list.test.js b/src/cli_keystore/list.test.js index 4ac7163a1c06b1..8e43a08fc9ff20 100644 --- a/src/cli_keystore/list.test.js +++ b/src/cli_keystore/list.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import mockFs from 'mock-fs'; @@ -7,7 +26,7 @@ import Logger from '../cli_plugin/lib/logger'; describe('Kibana keystore', () => { describe('list', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); const keystoreData = '1:IxR0geiUTMJp8ueHDkqeUJ0I9eEw4NJPXIJi22UDyfGfJSy4mH' + 'BBuGPkkAix/x/YFfIxo4tiKGdJ2oVTtU8LgKDkVoGdL+z7ylY4n3myatt6osqhI4lzJ9M' diff --git a/src/cli_keystore/remove.js b/src/cli_keystore/remove.js index 627f557f81b49c..391fe426a49987 100644 --- a/src/cli_keystore/remove.js +++ b/src/cli_keystore/remove.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export async function remove(keystore, key) { keystore.remove(key); keystore.save(); diff --git a/src/cli_keystore/remove.test.js b/src/cli_keystore/remove.test.js index 020b6e6f021b26..9be73b128af213 100644 --- a/src/cli_keystore/remove.test.js +++ b/src/cli_keystore/remove.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import mockFs from 'mock-fs'; @@ -6,7 +25,7 @@ import { remove } from './remove'; describe('Kibana keystore', () => { describe('remove', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); const keystoreData = '1:IxR0geiUTMJp8ueHDkqeUJ0I9eEw4NJPXIJi22UDyfGfJSy4mH' + 'BBuGPkkAix/x/YFfIxo4tiKGdJ2oVTtU8LgKDkVoGdL+z7ylY4n3myatt6osqhI4lzJ9M' diff --git a/src/cli_plugin/cli.js b/src/cli_plugin/cli.js index bd7023d639ab96..223f8e6e4764c9 100644 --- a/src/cli_plugin/cli.js +++ b/src/cli_plugin/cli.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { pkg } from '../utils'; import Command from '../cli/command'; diff --git a/src/cli_plugin/index.js b/src/cli_plugin/index.js index d5b8a863770511..4af5e3c68423cd 100644 --- a/src/cli_plugin/index.js +++ b/src/cli_plugin/index.js @@ -1,2 +1,21 @@ -require('../babel-register'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +require('../setup_node_env'); require('./cli'); diff --git a/src/cli_plugin/install/cleanup.js b/src/cli_plugin/install/cleanup.js index e6b6a899126dea..631257fba72716 100644 --- a/src/cli_plugin/install/cleanup.js +++ b/src/cli_plugin/install/cleanup.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import rimraf from 'rimraf'; import fs from 'fs'; diff --git a/src/cli_plugin/install/cleanup.test.js b/src/cli_plugin/install/cleanup.test.js index 76e115e94d1d1b..a0f5f5064102ce 100644 --- a/src/cli_plugin/install/cleanup.test.js +++ b/src/cli_plugin/install/cleanup.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import fs from 'fs'; import rimraf from 'rimraf'; @@ -34,7 +53,7 @@ describe('kibana cli', function () { it('should resolve if the working path does not exist', function () { sinon.stub(rimraf, 'sync'); - sinon.stub(fs, 'statSync', function () { + sinon.stub(fs, 'statSync').callsFake(() => { const error = new Error('ENOENT'); error.code = 'ENOENT'; throw error; @@ -49,10 +68,7 @@ describe('kibana cli', function () { it('should rethrow any exception except ENOENT from fs.statSync', function () { sinon.stub(rimraf, 'sync'); - sinon.stub(fs, 'statSync', function () { - const error = new Error('An Unhandled Error'); - throw error; - }); + sinon.stub(fs, 'statSync').throws(new Error('An Unhandled Error')); errorStub = sinon.stub(); return cleanPrevious(settings, logger) @@ -75,9 +91,7 @@ describe('kibana cli', function () { it('should rethrow any exception from rimraf.sync', function () { sinon.stub(fs, 'statSync'); - sinon.stub(rimraf, 'sync', function () { - throw new Error('I am an error thrown by rimraf'); - }); + sinon.stub(rimraf, 'sync').throws(new Error('I am an error thrown by rimraf')); errorStub = sinon.stub(); return cleanPrevious(settings, logger) @@ -114,9 +128,7 @@ describe('kibana cli', function () { }); it('should swallow any errors thrown by rimraf.sync', function () { - sinon.stub(rimraf, 'sync', function () { - throw new Error('Something bad happened.'); - }); + sinon.stub(rimraf, 'sync').throws(new Error('Something bad happened.')); expect(() => cleanArtifacts(settings)).not.toThrow(); }); diff --git a/src/cli_plugin/install/download.js b/src/cli_plugin/install/download.js index c505f8fd8a67c0..1fb985ee3d6b5c 100644 --- a/src/cli_plugin/install/download.js +++ b/src/cli_plugin/install/download.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import downloadHttpFile from './downloaders/http'; import downloadLocalFile from './downloaders/file'; import { UnsupportedProtocolError } from '../lib/errors'; diff --git a/src/cli_plugin/install/download.test.js b/src/cli_plugin/install/download.test.js index 751f436550e6e0..97586f962737c8 100644 --- a/src/cli_plugin/install/download.test.js +++ b/src/cli_plugin/install/download.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import nock from 'nock'; import glob from 'glob-all'; diff --git a/src/cli_plugin/install/downloaders/file.js b/src/cli_plugin/install/downloaders/file.js index febce55d6a987a..56f83b03d5a907 100644 --- a/src/cli_plugin/install/downloaders/file.js +++ b/src/cli_plugin/install/downloaders/file.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Progress from '../progress'; import { createWriteStream, createReadStream, statSync } from 'fs'; diff --git a/src/cli_plugin/install/downloaders/http.js b/src/cli_plugin/install/downloaders/http.js index acd02e81f455b7..a704f3df77c1d9 100644 --- a/src/cli_plugin/install/downloaders/http.js +++ b/src/cli_plugin/install/downloaders/http.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Wreck from 'wreck'; import Progress from '../progress'; import { fromNode as fn } from 'bluebird'; diff --git a/src/cli_plugin/install/index.js b/src/cli_plugin/install/index.js index 0d72fe01c77ec5..f4848bfc075418 100644 --- a/src/cli_plugin/install/index.js +++ b/src/cli_plugin/install/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fromRoot, pkg } from '../../utils'; import install from './install'; import Logger from '../lib/logger'; diff --git a/src/cli_plugin/install/index.test.js b/src/cli_plugin/install/index.test.js index c8edbc5b4cf7f8..5eda6b985abee5 100644 --- a/src/cli_plugin/install/index.test.js +++ b/src/cli_plugin/install/index.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import index from './index'; diff --git a/src/cli_plugin/install/install.js b/src/cli_plugin/install/install.js index 13fcd9782dcbde..75d83b9762daf8 100644 --- a/src/cli_plugin/install/install.js +++ b/src/cli_plugin/install/install.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { download } from './download'; import Promise from 'bluebird'; import path from 'path'; diff --git a/src/cli_plugin/install/kibana.js b/src/cli_plugin/install/kibana.js index d14f9a83d73048..675cc180a9d944 100644 --- a/src/cli_plugin/install/kibana.js +++ b/src/cli_plugin/install/kibana.js @@ -1,8 +1,25 @@ -import _ from 'lodash'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import path from 'path'; -import { fromRoot } from '../../utils'; -import KbnServer from '../../server/kbn_server'; -import { readYamlConfig } from '../../cli/serve/read_yaml_config'; +import execa from 'execa'; +import { fromRoot, watchStdioForLine } from '../../utils'; import { versionSatisfies, cleanVersion } from '../../utils/version'; import { statSync } from 'fs'; @@ -19,34 +36,22 @@ export function existingInstall(settings, logger) { export async function rebuildCache(settings, logger) { logger.log('Optimizing and caching browser bundles...'); - const serverConfig = _.merge( - readYamlConfig(settings.config), - { - env: 'production', - logging: { - silent: settings.silent, - quiet: !settings.silent, - verbose: false - }, - optimize: { - useBundleCache: false - }, - server: { - autoListen: false - }, - plugins: { - initialize: false, - scanDirs: [settings.pluginDir, fromRoot('src/core_plugins')] - }, - uiSettings: { - enabled: false - } - } - ); - - const kbnServer = new KbnServer(serverConfig); - await kbnServer.ready(); - await kbnServer.close(); + + const kibanaArgs = [ + fromRoot('./src/cli'), + '--env.name=production', + '--optimize.useBundleCache=false', + '--server.autoListen=false', + '--plugins.initialize=false', + '--uiSettings.enabled=false' + ]; + + const proc = execa(process.execPath, kibanaArgs, { + stdio: ['ignore', 'pipe', 'pipe'], + cwd: fromRoot('.'), + }); + + await watchStdioForLine(proc, () => {}, /Optimization .+ complete/); } export function assertVersion(settings) { diff --git a/src/cli_plugin/install/kibana.test.js b/src/cli_plugin/install/kibana.test.js index 552b8ab2309552..641c3da09807bc 100644 --- a/src/cli_plugin/install/kibana.test.js +++ b/src/cli_plugin/install/kibana.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import mockFs from 'mock-fs'; import Logger from '../lib/logger'; diff --git a/src/cli_plugin/install/pack.js b/src/cli_plugin/install/pack.js index c4bcad1846eb77..87c94fce2b6777 100644 --- a/src/cli_plugin/install/pack.js +++ b/src/cli_plugin/install/pack.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { analyzeArchive, extractArchive } from './zip'; import validate from 'validate-npm-package-name'; diff --git a/src/cli_plugin/install/pack.test.js b/src/cli_plugin/install/pack.test.js index 85e7e2635b269f..bc854f66a6925f 100644 --- a/src/cli_plugin/install/pack.test.js +++ b/src/cli_plugin/install/pack.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import glob from 'glob-all'; import rimraf from 'rimraf'; diff --git a/src/cli_plugin/install/progress.js b/src/cli_plugin/install/progress.js index dca7f9a2b88fcb..8a8c0c5d8b3ca4 100644 --- a/src/cli_plugin/install/progress.js +++ b/src/cli_plugin/install/progress.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Generates file transfer progress messages */ diff --git a/src/cli_plugin/install/progress.test.js b/src/cli_plugin/install/progress.test.js index 42d22aa592aea1..91171a5b2eb7ee 100644 --- a/src/cli_plugin/install/progress.test.js +++ b/src/cli_plugin/install/progress.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import Progress from './progress'; import Logger from '../lib/logger'; diff --git a/src/cli_plugin/install/rename.js b/src/cli_plugin/install/rename.js index 10f65c7657a16d..b01769cfdacd92 100644 --- a/src/cli_plugin/install/rename.js +++ b/src/cli_plugin/install/rename.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { rename } from 'fs'; import { delay } from 'lodash'; diff --git a/src/cli_plugin/install/rename.test.js b/src/cli_plugin/install/rename.test.js index 3e2fb633a709e4..2ba3ce9afc9983 100644 --- a/src/cli_plugin/install/rename.test.js +++ b/src/cli_plugin/install/rename.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import fs from 'fs'; @@ -15,7 +34,7 @@ describe('plugin folder rename', function () { }); it('should rethrow any exceptions', function () { - renameStub = sinon.stub(fs, 'rename', function (from, to, cb) { + renameStub = sinon.stub(fs, 'rename').callsFake((from, to, cb) => { cb({ code: 'error' }); @@ -29,7 +48,7 @@ describe('plugin folder rename', function () { }); it('should resolve if there are no errors', function () { - renameStub = sinon.stub(fs, 'rename', function (from, to, cb) { + renameStub = sinon.stub(fs, 'rename').callsFake((from, to, cb) => { cb(); }); @@ -55,7 +74,7 @@ describe('plugin folder rename', function () { }); it('should retry on Windows EPERM errors for up to 3 seconds', function () { - renameStub = sinon.stub(fs, 'rename', function (from, to, cb) { + renameStub = sinon.stub(fs, 'rename').callsFake((from, to, cb) => { cb({ code: 'EPERM' }); diff --git a/src/cli_plugin/install/settings.js b/src/cli_plugin/install/settings.js index 628ae5b72203dc..df34a1490f8e1c 100644 --- a/src/cli_plugin/install/settings.js +++ b/src/cli_plugin/install/settings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expiry from 'expiry-js'; import { resolve } from 'path'; diff --git a/src/cli_plugin/install/settings.test.js b/src/cli_plugin/install/settings.test.js index 9a9971a93f75f0..083fd240ed4c7b 100644 --- a/src/cli_plugin/install/settings.test.js +++ b/src/cli_plugin/install/settings.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fromRoot } from '../../utils'; import { resolve } from 'path'; import { parseMilliseconds, parse } from './settings'; diff --git a/src/cli_plugin/install/zip.js b/src/cli_plugin/install/zip.js index a9445748dc2054..25cdac42398db0 100644 --- a/src/cli_plugin/install/zip.js +++ b/src/cli_plugin/install/zip.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import yauzl from 'yauzl'; import path from 'path'; import mkdirp from 'mkdirp'; diff --git a/src/cli_plugin/install/zip.test.js b/src/cli_plugin/install/zip.test.js index c144a0a5ef518c..516e0abe25743d 100644 --- a/src/cli_plugin/install/zip.test.js +++ b/src/cli_plugin/install/zip.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import rimraf from 'rimraf'; import path from 'path'; import os from 'os'; diff --git a/src/cli_plugin/lib/__tests__/error_if_x_pack.js b/src/cli_plugin/lib/__tests__/error_if_x_pack.js index 709ebf3aa9c770..d169f16a3bebe5 100644 --- a/src/cli_plugin/lib/__tests__/error_if_x_pack.js +++ b/src/cli_plugin/lib/__tests__/error_if_x_pack.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import sinon from 'sinon'; diff --git a/src/cli_plugin/lib/__tests__/is_oss.js b/src/cli_plugin/lib/__tests__/is_oss.js index 8b5e03b79feeda..117d622789de4c 100644 --- a/src/cli_plugin/lib/__tests__/is_oss.js +++ b/src/cli_plugin/lib/__tests__/is_oss.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { isOSS } from '../is_oss'; diff --git a/src/cli_plugin/lib/error_if_x_pack.js b/src/cli_plugin/lib/error_if_x_pack.js index 070955e233a692..4c808ac34d52de 100644 --- a/src/cli_plugin/lib/error_if_x_pack.js +++ b/src/cli_plugin/lib/error_if_x_pack.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { isOSS } from './is_oss'; function isXPack(plugin) { diff --git a/src/cli_plugin/lib/errors.js b/src/cli_plugin/lib/errors.js index 43e135fe0e706e..7daac0e934543e 100644 --- a/src/cli_plugin/lib/errors.js +++ b/src/cli_plugin/lib/errors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function UnsupportedProtocolError() { Error.call(this, 'Unsupported protocol'); } diff --git a/src/cli_plugin/lib/is_oss.js b/src/cli_plugin/lib/is_oss.js index c470160e0bb46e..b19e090cd2193b 100644 --- a/src/cli_plugin/lib/is_oss.js +++ b/src/cli_plugin/lib/is_oss.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function isOSS() { try { require.resolve('x-pack'); diff --git a/src/cli_plugin/lib/log_warnings.js b/src/cli_plugin/lib/log_warnings.js index b92b049a0baa76..9bcc992c2a648a 100644 --- a/src/cli_plugin/lib/log_warnings.js +++ b/src/cli_plugin/lib/log_warnings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function (settings, logger) { process.on('warning', warning => { // deprecation warnings do no reflect a current problem for diff --git a/src/cli_plugin/lib/logger.js b/src/cli_plugin/lib/logger.js index 11dd761220fb7d..ba6a0e7d682f8a 100644 --- a/src/cli_plugin/lib/logger.js +++ b/src/cli_plugin/lib/logger.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Logs messages and errors */ diff --git a/src/cli_plugin/lib/logger.test.js b/src/cli_plugin/lib/logger.test.js index 0c235da7f495c1..641a976f6ae8c9 100644 --- a/src/cli_plugin/lib/logger.test.js +++ b/src/cli_plugin/lib/logger.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import Logger from './logger'; diff --git a/src/cli_plugin/lib/warn_if_plugin_dir_option.js b/src/cli_plugin/lib/warn_if_plugin_dir_option.js index 94bbdf8dd3e541..05e85938ae3e57 100644 --- a/src/cli_plugin/lib/warn_if_plugin_dir_option.js +++ b/src/cli_plugin/lib/warn_if_plugin_dir_option.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function warnIfUsingPluginDirOption(options, defaultValue, logger) { if (options && options.pluginDir !== defaultValue) { logger.log( diff --git a/src/cli_plugin/list/index.js b/src/cli_plugin/list/index.js index 2ab80209d2118a..70bf7053843f5d 100644 --- a/src/cli_plugin/list/index.js +++ b/src/cli_plugin/list/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fromRoot } from '../../utils'; import list from './list'; import Logger from '../lib/logger'; diff --git a/src/cli_plugin/list/list.js b/src/cli_plugin/list/list.js index 4b3ad155ced7cc..c0d633cedf970e 100644 --- a/src/cli_plugin/list/list.js +++ b/src/cli_plugin/list/list.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { statSync, readdirSync, readFileSync } from 'fs'; import { join } from 'path'; diff --git a/src/cli_plugin/list/list.test.js b/src/cli_plugin/list/list.test.js index be3c4dcc2540a1..c72f6c330543ca 100644 --- a/src/cli_plugin/list/list.test.js +++ b/src/cli_plugin/list/list.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import rimraf from 'rimraf'; import mkdirp from 'mkdirp'; diff --git a/src/cli_plugin/list/settings.js b/src/cli_plugin/list/settings.js index b4f59581c08f0f..cd5917e5729aa8 100644 --- a/src/cli_plugin/list/settings.js +++ b/src/cli_plugin/list/settings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function parse(command) { const settings = { pluginDir: command.pluginDir || '' diff --git a/src/cli_plugin/list/settings.test.js b/src/cli_plugin/list/settings.test.js index fb008d8f1b7a60..1b765064573aff 100644 --- a/src/cli_plugin/list/settings.test.js +++ b/src/cli_plugin/list/settings.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fromRoot } from '../../utils'; import { parse } from './settings'; diff --git a/src/cli_plugin/remove/index.js b/src/cli_plugin/remove/index.js index ea64667626a982..52c46173d41a4a 100644 --- a/src/cli_plugin/remove/index.js +++ b/src/cli_plugin/remove/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fromRoot } from '../../utils'; import remove from './remove'; import Logger from '../lib/logger'; diff --git a/src/cli_plugin/remove/remove.js b/src/cli_plugin/remove/remove.js index 907a21a19b4de9..ae1bf245e34d4c 100644 --- a/src/cli_plugin/remove/remove.js +++ b/src/cli_plugin/remove/remove.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { statSync } from 'fs'; import { errorIfXPackRemove } from '../lib/error_if_x_pack'; diff --git a/src/cli_plugin/remove/remove.test.js b/src/cli_plugin/remove/remove.test.js index 28362096e1d4c4..1208fcb5597304 100644 --- a/src/cli_plugin/remove/remove.test.js +++ b/src/cli_plugin/remove/remove.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import glob from 'glob-all'; import rimraf from 'rimraf'; diff --git a/src/cli_plugin/remove/settings.js b/src/cli_plugin/remove/settings.js index 105902687b355b..99e26ef930e3d9 100644 --- a/src/cli_plugin/remove/settings.js +++ b/src/cli_plugin/remove/settings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve } from 'path'; export function parse(command, options) { diff --git a/src/cli_plugin/remove/settings.test.js b/src/cli_plugin/remove/settings.test.js index 92bbdb591d7497..984caaf3be3ec0 100644 --- a/src/cli_plugin/remove/settings.test.js +++ b/src/cli_plugin/remove/settings.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fromRoot } from '../../utils'; import { parse } from './settings'; diff --git a/src/core_plugins/console/__tests__/index.js b/src/core_plugins/console/__tests__/index.js index 8489a7a532e700..aebb5e16bc6d22 100644 --- a/src/core_plugins/console/__tests__/index.js +++ b/src/core_plugins/console/__tests__/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Deprecations } from '../../../deprecation'; import expect from 'expect.js'; import index from '../index'; diff --git a/src/core_plugins/console/api_server/api.js b/src/core_plugins/console/api_server/api.js index 671d8c7a139820..4b955d015649dd 100644 --- a/src/core_plugins/console/api_server/api.js +++ b/src/core_plugins/console/api_server/api.js @@ -1,45 +1,70 @@ -const _ = require("lodash"); - -'use strict'; - -/** +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 * - * @param name + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ -function Api(name) { - this.globalRules = {}; - this.endpoints = {}; - this.name = name; -} -(function (cls) { - cls.addGlobalAutocompleteRules = function (parentNode, rules) { - this.globalRules[parentNode] = rules; - }; +import _ from 'lodash'; - cls.addEndpointDescription = function (endpoint, description) { +class Api { + constructor(name) { + this.globalRules = {}; + this.endpoints = {}; + this.name = name; + } + addGlobalAutocompleteRules = function (parentNode, rules) { + this.globalRules[parentNode] = rules; + } + addEndpointDescription(endpoint, description = {}) { + let copiedDescription = {}; if (this.endpoints[endpoint]) { - throw new Error("endpoint [" + endpoint + "] is already registered"); + copiedDescription = { ...this.endpoints[endpoint] }; + } + let urlParamsDef; + _.each(description.patterns || [], function (p) { + if (p.indexOf('{indices}') >= 0) { + urlParamsDef = urlParamsDef || {}; + urlParamsDef.ignore_unavailable = '__flag__'; + urlParamsDef.allow_no_indices = '__flag__'; + urlParamsDef.expand_wildcards = ['open', 'closed']; + } + }); + + if (urlParamsDef) { + description.url_params = _.extend(description.url_params || {}, copiedDescription.url_params); + _.defaults(description.url_params, urlParamsDef); } - var copiedDescription = {}; - _.extend(copiedDescription, description || {}); + _.extend(copiedDescription, description); _.defaults(copiedDescription, { id: endpoint, patterns: [endpoint], methods: ['GET'] }); this.endpoints[endpoint] = copiedDescription; - }; + } - cls.asJson = function () { + asJson() { return { - "name": this.name, - "globals": this.globalRules, - "endpoints": this.endpoints - } - }; + 'name': this.name, + 'globals': this.globalRules, + 'endpoints': this.endpoints + }; + } -}(Api.prototype)); +} export default Api; diff --git a/src/core_plugins/console/api_server/es_5_0.js b/src/core_plugins/console/api_server/es_5_0.js deleted file mode 100644 index c00fa5644c347b..00000000000000 --- a/src/core_plugins/console/api_server/es_5_0.js +++ /dev/null @@ -1,56 +0,0 @@ -let _ = require("lodash"); -let Api = require('./api'); -import { getSpec } from './spec' -let parts = [ - require('./es_5_0/aliases'), - require('./es_5_0/aggregations'), - require('./es_5_0/document'), - require('./es_5_0/filter'), - require('./es_5_0/nodes'), - require('./es_5_0/globals'), - require('./es_5_0/ingest'), - require('./es_5_0/mappings'), - require('./es_5_0/percolator'), - require('./es_5_0/query'), - require('./es_5_0/reindex'), - require('./es_5_0/search'), -]; - -function ES_5_0() { - Api.call(this, "es_5_0"); - _.each(parts, function (apiSection) { - apiSection(this); - }, this); - - const spec = getSpec() - Object.keys(spec).forEach(endpoint => { - this.addEndpointDescription(endpoint, spec[endpoint]) - }) -} - -ES_5_0.prototype = _.create(Api.prototype, { 'constructor': ES_5_0 }); - -(function (cls) { - cls.addEndpointDescription = function (endpoint, description) { - if (description) { - var url_params_def = {}; - _.each(description.patterns || [], function (p) { - if (p.indexOf("{indices}") >= 0) { - url_params_def["ignore_unavailable"] = "__flag__"; - url_params_def["allow_no_indices"] = "__flag__"; - url_params_def["expand_wildcards"] = ["open", "closed"]; - } - }); - - if (url_params_def) { - description.url_params = description.url_params || {}; - _.defaults(description.url_params, url_params_def); - } - } - Object.getPrototypeOf(cls).addEndpointDescription.call(this, endpoint, description); - }; -})(ES_5_0.prototype); - -const instance = new ES_5_0(); - -export default instance; diff --git a/src/core_plugins/console/api_server/es_5_0/aggregations.js b/src/core_plugins/console/api_server/es_5_0/aggregations.js deleted file mode 100644 index 9faaaffb39193a..00000000000000 --- a/src/core_plugins/console/api_server/es_5_0/aggregations.js +++ /dev/null @@ -1,478 +0,0 @@ -var simple_metric = { - __template: { field: "" }, - field: "{field}", - missing: 0, - script: { - // populated by a global rule - } -}, field_metric = { - __template: { field: "" }, - field: "{field}" -}, gap_policy = { - __one_of: ["skip", "insert_zeros"] -}, simple_pipeline = { - __template: { - buckets_path: "" - }, - buckets_path: "", - format: "", - gap_policy: gap_policy -}; -var rules = { - "*": { - "aggs": { - __template: { - "NAME": { - "AGG_TYPE": {} - } - } - }, - "min": simple_metric, - "max": simple_metric, - "avg": simple_metric, - "sum": simple_metric, - "stats": simple_metric, - "extended_stats": simple_metric, - "value_count": { - __template: { - "field": "" - }, - "field": "{field}", - "script": { - // populated by a global rule - } - }, - "global": {}, - "filter": {}, - "filters": { - __template: { - "filters": { - "NAME": {} - } - }, - "filters": { - "*": { __scope_link: "GLOBAL.filter" } - }, - "other_bucket": { __one_of: [true, false] }, - "other_bucket_key": "" - }, - "missing": field_metric, - "nested": { - __template: { - "path": "" - }, - "path": "" - }, - "reverse_nested": { - __template: { - "path": "" - }, - "path": "" - }, - "terms": { - __template: { - "field": "", - "size": 10 - }, - "field": "{field}", - "size": 10, - "shard_size": 10, - "order": { - __template: { - "_term": "asc" - }, - "_term": { __one_of: ["asc", "desc"] }, - "_count": { __one_of: ["asc", "desc"] }, - "*": { __one_of: ["asc", "desc"] } - }, - "min_doc_count": 10, - "script": { - // populated by a global rule - }, - "include": ".*", - "exclude": ".*", - "execution_hint": { __one_of: ["map", "global_ordinals", "global_ordinals_hash", "global_ordinals_low_cardinality"] }, - "show_term_doc_count_error": { __one_of: [true, false] }, - "collect_mode": { __one_of: ["depth_first", "breadth_first"] }, - "missing": "" - }, - "significant_terms": { - __template: { - "field": "" - }, - "field": "{field}", - "size": 10, - "shard_size": 10, - "shard_min_doc_count": 10, - "min_doc_count": 10, - "include": { __one_of: ["*", { pattern: "", flags: "" }] }, - "exclude": { __one_of: ["*", { pattern: "", flags: "" }] }, - "execution_hint": { __one_of: ["map", "global_ordinals", "global_ordinals_hash"] }, - "background_filter": { - __scope_link: "GLOBAL.filter" - }, - "mutual_information": { - "include_negatives": { __one_of: [true, false] } - }, - "chi_square": { - "include_negatives": { __one_of: [true, false] }, - "background_is_superset": { __one_of: [true, false] } - }, - "percentage": {}, - "gnd": { - "background_is_superset": { __one_of: [true, false] } - }, - "script_heuristic": { - __template: { - "script": "_subset_freq/(_superset_freq - _subset_freq + 1)" - }, - "script": { - // populated by a global rule - } - } - }, - "range": { - __template: { - "field": "", - "ranges": [ - { "from": 50, "to": 100 }, - ] - }, - "field": "{field}", - "ranges": [ - { "to": 50, "from": 100, "key": "" } - ], - "keyed": { __one_of: [true, false] }, - "script": { - // populated by a global rule - } - }, - "date_range": { - __template: { - "field": "", - "ranges": [ - { "from": "now-10d/d", "to": "now" }, - ] - }, - "field": "{field}", - "format": "MM-yyy", - "ranges": [ - { "to": "", "from": "", "key": "" } - ], - "keyed": { __one_of: [true, false] }, - "script": { - // populated by a global rule - } - }, - "ip_range": { - __template: { - "field": "", - "ranges": [ - { "from": "10.0.0.5", "to": "10.0.0.10" }, - ] - }, - "field": "{field}", - "format": "MM-yyy", - "ranges": [ - { "to": "", "from": "", "key": "", "mask": "10.0.0.127/25" } - ], - "keyed": { __one_of: [true, false] }, - "script": { - // populated by a global rule - } - }, - "histogram": { - __template: { - "field": "price", - "interval": 50 - }, - "field": "{field}", - "interval": 50, - "extended_bounds": { - "__template": { - "min": 0, - "max": 50 - }, - "min": 0, - "max": 50 - }, - "min_doc_count": 0, - "order": { - __template: { - "_key": "asc" - }, - "_key": { __one_of: ["asc", "desc"] }, - "_count": { __one_of: ["asc", "desc"] }, - "*": { __one_of: ["asc", "desc"] } - }, - "keyed": { __one_of: [true, false] }, - "missing": 0 - }, - "date_histogram": { - __template: { - "field": "date", - "interval": "month" - }, - "field": "{field}", - "interval": { __one_of: ["year", "quarter", "week", "day", "hour", "minute", "second"] }, - "min_doc_count": 0, - "extended_bounds": { - "__template": { - "min": "now/d", - "max": "now/d" - }, - "min": "now/d", - "max": "now/d" - }, - "order": { - __template: { - "_key": "asc" - }, - "_key": { __one_of: ["asc", "desc"] }, - "_count": { __one_of: ["asc", "desc"] }, - "*": { __one_of: ["asc", "desc"] } - }, - "keyed": { __one_of: [true, false] }, - "pre_zone": "-01:00", - "post_zone": "-01:00", - "pre_zone_adjust_large_interval": { __one_of: [true, false] }, - "factor": 1000, - "pre_offset": "1d", - "post_offset": "1d", - "format": "yyyy-MM-dd", - "time_zone": "00:00", - "missing": "" - }, - "geo_distance": { - __template: { - "field": "location", - "origin": { "lat": 52.3760, "lon": 4.894 }, - "ranges": [ - { "from": 100, "to": 300 }, - ] - }, - "field": "{field}", - "origin": { "lat": 0.0, "lon": 0.0 }, - "unit": { __one_of: ["mi", "km", "in", "yd", "m", "cm", "mm"] }, - "ranges": [ - { "from": 50, "to": 100 } - ], - "distance_type": { __one_of: ["arc", "sloppy_arc", "plane"] } - - }, - "geohash_grid": { - __template: { - "field": "", - "precision": 3 - }, - "field": "{field}", - "precision": { __one_of: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] }, - "size": 10, - "shard_size": 10 - }, - "composite": { - __template: { - "sources": [ - { - "NAME": { - "AGG_TYPE": {} - } - } - ] - }, - "sources": [ - { - __scope_link: ".", - __template: { - "NAME": { - "AGG_TYPE": {} - } - } - } - ], - "size": 10, - "after": {} - }, - "percentiles": { - __template: { - "field": "", - "percents": [1.0, 5.0, 25.0, 50.0, 75.0, 95.0, 99.0] - }, - "field": "{field}", - "percents": { - __template: [1.0, 5.0, 25.0, 50.0, 75.0, 95.0, 99.0], - // mark type as list - __any_of: [] - }, - "script": { - // populated by a global rule - }, - "compression": 100, - "method": { __one_of: ["hdr", "tdigest"] }, - missing: 0 - }, - "cardinality": { - __template: { - "field": "" - }, - "precision_threshold": 100, - "rehash": true, - "script": { - // populated by a global rule - }, - missing: "" - }, - "scripted_metric": { - __template: { - "init_script": "", - "map_script": "", - "combine_script": "", - "reduce_script": "" - }, - "init_script": { - __scope_link: "GLOBAL.script" - }, - "map_script": { - __scope_link: "GLOBAL.script" - }, - "combine_script": { - __scope_link: "GLOBAL.script" - }, - "reduce_script": { - __scope_link: "GLOBAL.script" - }, - "lang": "groovy", - "params": {}, - "reduce_params": {} - }, - "geo_bounds": { - __template: { - field: "" - }, - field: "{field}", - wrap_longitude: { __one_of: [true, false] } - }, - "top_hits": { - __template: { - size: 10 - }, - from: 0, - size: 10, - sort: { - __template: [], - __scope_link: "_search.sort" - }, - highlight: {}, - explain: { __one_of: [true, false] }, - _source: { - __template: "", - __scope_link: "_search._source" - }, - script_fields: { - __scope_link: "_search.script_fields" - }, - docvalue_fields: ["{field}"], - version: { __one_of: [true, false] } - }, - "percentile_ranks": { - __template: { - field: "", - values: [10, 15] - }, - field: "{field}", - values: [], - "script": { - // populated by a global rule - }, - "compression": 100, - "method": { __one_of: ["hdr", "tdigest"] }, - missing: 0 - }, - "sampler": { - __template: {}, - "field": "{field}", - "script": { - // populated by a global rule - }, - "shard_size": 100, - "max_docs_per_value": 3, - "execution_hint": { __one_of: ["map", "global_ordinals", "bytes_hash"] } - }, - "children": { - __template: { - "type": "", - }, - "type": "" - }, - "derivative": simple_pipeline, - "avg_bucket": simple_pipeline, - "max_bucket": simple_pipeline, - "min_bucket": simple_pipeline, - "sum_bucket": simple_pipeline, - "moving_avg": { - __template: { - buckets_path: "" - }, - buckets_path: "", - format: "", - gap_policy: gap_policy, - "window": 5, - model: { __one_of: ["simple", "linear", "ewma", "holt", "holt_winters"] }, - settings: { - type: { __one_of: ["add", "mult"] }, - alpha: 0.5, - beta: 0.5, - gamma: 0.5, - period: 7 - } - }, - "cumulative_sum": { - __template: { - buckets_path: "" - }, - buckets_path: "", - format: "" - }, - "serial_diff": { - __template: { - buckets_path: "", - lag: 7 - }, - lag: 7, - gap_policy: gap_policy, - buckets_path: "", - format: "" - }, - "bucket_script": { - __template: { - buckets_path: {}, - script: "" - }, - buckets_path: {}, - format: "", - gap_policy: gap_policy, - script: "" - }, - "bucket_selector": { - __template: { - buckets_path: {}, - script: "" - }, - buckets_path: {}, - gap_policy: gap_policy, - script: "" - }, - "matrix_stats": { - __template: { - fields: [] - }, - fields: ["{field}"] - } - } -}; - -export default function (api) { - - api.addGlobalAutocompleteRules('aggregations', rules); - api.addGlobalAutocompleteRules('aggs', rules); -} diff --git a/src/core_plugins/console/api_server/es_5_0/aliases.js b/src/core_plugins/console/api_server/es_5_0/aliases.js deleted file mode 100644 index ca2ea6114ef2cb..00000000000000 --- a/src/core_plugins/console/api_server/es_5_0/aliases.js +++ /dev/null @@ -1,26 +0,0 @@ -export default function (api) { - api.addEndpointDescription('_get_aliases', { - methods: ['GET'], - patterns: [ - "_aliases", - ] - }); - - var aliasRules = { - filter: {}, - routing: '1', - search_routing: '1,2', - index_routing: '1' - }; - - api.addEndpointDescription('_delete_alias', { - methods: ["DELETE"], - patterns: [ - "{indices}/_alias/{name}" - ] - }); - - api.addGlobalAutocompleteRules('aliases', { - '*': aliasRules - }); -} diff --git a/src/core_plugins/console/api_server/es_5_0/document.js b/src/core_plugins/console/api_server/es_5_0/document.js deleted file mode 100644 index 2073a147f96b29..00000000000000 --- a/src/core_plugins/console/api_server/es_5_0/document.js +++ /dev/null @@ -1,141 +0,0 @@ -export default function (api) { - api.addEndpointDescription('_update', { - methods: ['POST'], - patterns: [ - "{index}/{type}/{id}/_update" - ], - url_params: { - "version": 1, - "version_type": ["force", "internal"], - "routing": "", - "parent": "", - "timestamp": "", - "consistency": ["qurom", "one", "all"], - "refresh": "__flag__", - "timeout": "1m", - "retry_on_conflict": 3, - "fields": "" - }, - data_autocomplete_rules: { - "script": { - // populated by a global rule - }, - "doc": {}, - "upsert": {}, - "scripted_upsert": { __one_of: [true, false] } - } - - }); - - api.addEndpointDescription('_put_script', { - methods: ['POST', 'PUT'], - patterns: [ - "_scripts/{lang}/{id}", - "_scripts/{lang}/{id}/_create" - ], - url_components: { - "lang": [ - "groovy", - "expressions" - ] - }, - data_autocomplete_rules: { - "script": "" - } - }); - - api.addEndpointDescription('_termvectors', { - methods: ['GET', 'POST'], - patterns: [ - "{index}/{type}/_termvectors" - ], - priority: 10, // collision with get doc - url_params: { - "fields": "", - "offsets": "__flag__", - "payloads": "__flag__", - "positions": "__flag__", - "term_statistics": "__flag__", - "field_statistics": "__flag__", - "routing": "", - "version": 1, - "version_type": ["external", "external_gt", "external_gte", "force", "internal"], - "parent": "", - "preference": "" - }, - data_autocomplete_rules: { - fields: [ - "{field}" - ], - offsets: { __one_of: [false, true] }, - payloads: { __one_of: [false, true] }, - positions: { __one_of: [false, true] }, - term_statistics: { __one_of: [true, false] }, - field_statistics: { __one_of: [false, true] }, - per_field_analyzer: { - __template: { "FIELD": "" }, - "{field}": "" - }, - routing: "", - version: 1, - version_type: ["external", "external_gt", "external_gte", "force", "internal"], - doc: {}, - filter: { // TODO: Exclude from global filter rules - "max_num_terms": 1, - "min_term_freq": 1, - "max_term_freq": 1, - "min_doc_freq": 1, - "max_doc_freq": 1, - "min_word_length": 1, - "max_word_length": 1 - } - } - }); - api.addEndpointDescription('_termvectors_id', { - methods: ['GET', 'POST'], - patterns: [ - "{index}/{type}/{id}/_termvectors" - ], - url_params: { - "fields": "", - "offsets": "__flag__", - "payloads": "__flag__", - "positions": "__flag__", - "term_statistics": "__flag__", - "field_statistics": "__flag__", - "routing": "", - "version": 1, - "version_type": ["external", "external_gt", "external_gte", "force", "internal"], - "parent": "", - "preference": "", - "dfs": "__flag__" - }, - data_autocomplete_rules: { - fields: [ - "{field}" - ], - offsets: { __one_of: [false, true] }, - payloads: { __one_of: [false, true] }, - positions: { __one_of: [false, true] }, - term_statistics: { __one_of: [true, false] }, - field_statistics: { __one_of: [false, true] }, - dfs: { __one_of: [true, false] }, - per_field_analyzer: { - __template: { "FIELD": "" }, - "{field}": "" - }, - routing: "", - version: 1, - version_type: ["external", "external_gt", "external_gte", "force", "internal"], - filter: { // TODO: Exclude from global filter rules - "max_num_terms": 1, - "min_term_freq": 1, - "max_term_freq": 1, - "min_doc_freq": 1, - "max_doc_freq": 1, - "min_word_length": 1, - "max_word_length": 1 - } - } - }); -} diff --git a/src/core_plugins/console/api_server/es_5_0/globals.js b/src/core_plugins/console/api_server/es_5_0/globals.js deleted file mode 100644 index c0b49f758f2154..00000000000000 --- a/src/core_plugins/console/api_server/es_5_0/globals.js +++ /dev/null @@ -1,24 +0,0 @@ -export default function (api) { - api.addGlobalAutocompleteRules('highlight', { - pre_tags: {}, - post_tags: {}, - tags_schema: {}, - fields: { - '{field}': { - fragment_size: 20, - number_of_fragments: 3 - } - } - }); - - api.addGlobalAutocompleteRules('script', { - __template: { - inline: "SCRIPT" - }, - inline: "SCRIPT", - file: "FILE_SCRIPT_NAME", - id: "SCRIPT_ID", - lang: "", - params: {} - }); -} diff --git a/src/core_plugins/console/api_server/es_5_0/mappings.js b/src/core_plugins/console/api_server/es_5_0/mappings.js deleted file mode 100644 index b950b81e14806e..00000000000000 --- a/src/core_plugins/console/api_server/es_5_0/mappings.js +++ /dev/null @@ -1,188 +0,0 @@ -let _ = require("lodash"); - -var BOOLEAN = { - __one_of: [true, false] -}; - -export default function (api) { - api.addEndpointDescription('_put_type_mapping', { - methods: ['PUT', 'POST'], - patterns: [ - "{indices}/{type}/_mapping", - "{indices}/_mapping/{type}" - ], - priority: 10, // collides with put doc by id - data_autocomplete_rules: { - __template: { - properties: { - 'FIELD': {} - } - }, - '_source': { - 'enabled': BOOLEAN - }, - '_all': { - 'enabled': BOOLEAN - }, - '_field_names': { - 'index': BOOLEAN - }, - '_routing': { - 'required': BOOLEAN, - }, - '_index': { - 'enabled': BOOLEAN - }, - '_parent': { - __template: { - 'type': '' - }, - 'type': '{type}' - }, - '_timestamp': { - 'enabled': BOOLEAN, - 'format': 'YYYY-MM-dd', - 'default': "" - }, - 'dynamic_date_formats': ['yyyy-MM-dd'], - 'date_detection': BOOLEAN, - 'numeric_detection': BOOLEAN, - 'properties': { - '*': { - type: { - __one_of: ['text', 'keyword', 'float', 'half_float', 'scaled_float', 'double', 'byte', 'short', 'integer', 'long', 'date', 'boolean', - 'binary', 'object', 'nested', "geo_point", "geo_shape" - ] - }, - - // strings - store: BOOLEAN, - index: BOOLEAN, - term_vector: { - __one_of: ['no', 'yes', 'with_offsets', 'with_positions', 'with_positions_offsets'] - }, - boost: 1.0, - null_value: '', - - norms: BOOLEAN, - - index_options: { - __one_of: ['docs', 'freqs', 'positions'] - }, - analyzer: 'standard', - search_analyzer: 'standard', - include_in_all: { - __one_of: [false, true] - }, - ignore_above: 10, - position_increment_gap: 0, - - // numeric - precision_step: 4, - ignore_malformed: BOOLEAN, - scaling_factor: 100, - - // geo_point - lat_lon: { - __one_of: [true, false] - }, - geohash: { - __one_of: [true, false] - }, - geohash_precision: '1m', - geohash_prefix: { - __one_of: [true, false] - }, - validate: { - __one_of: [true, false] - }, - validate_lat: { - __one_of: [true, false] - }, - validate_lon: { - __one_of: [true, false] - }, - normalize: { - __one_of: [true, false] - }, - normalize_lat: { - __one_of: [true, false] - }, - normalize_lon: { - __one_of: [true, false] - }, - - // geo_shape - tree: { - __one_of: ['geohash', 'quadtree'] - }, - precision: '5km', - tree_levels: 12, - distance_error_pct: 0.025, - orientation: 'ccw', - - // dates - format: { - __one_of: _.flatten([_.map(['date', 'date_time', 'date_time_no_millis', - 'ordinal_date', 'ordinal_date_time', 'ordinal_date_time_no_millis', - 'time', 'time_no_millis', 't_time', 't_time_no_millis', - 'week_date', 'week_date_time', 'week_date_time_no_millis'], function (s) { - return ['basic_' + s, 'strict_' + s]; - }), - [ - 'date', 'date_hour', 'date_hour_minute', 'date_hour_minute_second', 'date_hour_minute_second_fraction', - 'date_hour_minute_second_millis', 'date_optional_time', 'date_time', 'date_time_no_millis', - 'hour', 'hour_minute', 'hour_minute_second', 'hour_minute_second_fraction', 'hour_minute_second_millis', - 'ordinal_date', 'ordinal_date_time', 'ordinal_date_time_no_millis', 'time', 'time_no_millis', - 't_time', 't_time_no_millis', 'week_date', 'week_date_time', 'weekDateTimeNoMillis', 'week_year', - 'weekyearWeek', 'weekyearWeekDay', 'year', 'year_month', 'year_month_day', 'epoch_millis', 'epoch_second' - ]]) - }, - - fielddata: { - filter: { - regex: '', - frequency: { - min: 0.001, - max: 0.1, - min_segment_size: 500 - } - } - }, - similarity: { - __one_of: ['default', 'BM25'] - }, - - // objects - properties: { - __scope_link: '_put_mapping.{type}.properties' - }, - - // multi_field - fields: { - '*': { - __scope_link: '_put_mapping.type.properties.field' - } - }, - copy_to: { __one_of: ['{field}', ['{field}']] }, - - // nested - include_in_parent: BOOLEAN, - include_in_root: BOOLEAN - } - } - } - - }); - api.addEndpointDescription('_put_mapping', { - methods: ['PUT'], - patterns: [ - "{indices}/_mapping" - ], - data_autocomplete_rules: { - '{type}': { - __scope_link: '_put_type_mapping' - } - } - }); -} diff --git a/src/core_plugins/console/api_server/es_5_0/nodes.js b/src/core_plugins/console/api_server/es_5_0/nodes.js deleted file mode 100644 index 04ea998b48f550..00000000000000 --- a/src/core_plugins/console/api_server/es_5_0/nodes.js +++ /dev/null @@ -1,78 +0,0 @@ -export default function (api) { - api.addEndpointDescription('_nodes/hot_threads', { - methods: ['GET'], - patterns: [ - "_nodes/hot_threads", - "_nodes/{nodes}/hot_threads" - ] - }); - api.addEndpointDescription('_nodes/info', { - patterns: [ - "_nodes", - "_nodes/{metrics}", - "_nodes/{nodes}", - "_nodes/{nodes}/{metrics}", - "_nodes/{nodes}/info/{metrics}" - ], - url_components: { - "metrics": [ - "settings", - "os", - "process", - "jvm", - "thread_pool", - "network", - "transport", - "http", - "plugins", - "ingest", - "_all" - ] - } - }); - api.addEndpointDescription('_nodes/stats', { - patterns: [ - "_nodes/stats", - "_nodes/stats/{metrics}", - "_nodes/stats/{metrics}/{index_metric}", - "_nodes/{nodes}/stats", - "_nodes/{nodes}/stats/{metrics}", - "_nodes/{nodes}/stats/{metrics}/{index_metric}" - ], - url_components: { - "metrics": [ - "os", - "jvm", - "thread_pool", - "network", - "fs", - "transport", - "http", - "indices", - "process", - "breaker", - "ingest", - "_all" - ], - "index_metric": [ - "store", - "indexing", - "get", - "search", - "merge", - "flush", - "refresh", - "filter_cache", - "fielddata", - "docs", - "warmer", - "percolate", - "completion", - "segments", - "translog", - "query_cache", - "_all" - ] - } - }); -} diff --git a/src/core_plugins/console/api_server/es_5_0/percolator.js b/src/core_plugins/console/api_server/es_5_0/percolator.js deleted file mode 100644 index ce3b07fcb43fff..00000000000000 --- a/src/core_plugins/console/api_server/es_5_0/percolator.js +++ /dev/null @@ -1,90 +0,0 @@ -export default function (api) { - api.addEndpointDescription('_put_percolator', { - priority: 10, // to override doc - methods: ['PUT', 'POST'], - patterns: [ - "{index}/.percolator/{id}" - ], - url_params: { - "version": 1, - "version_type": ["external", "internal"], - "op_type": ["create"], - "routing": "", - "parent": "", - "timestamp": "", - "ttl": "5m", - "consistency": ["qurom", "one", "all"], - "refresh": "__flag__", - "timeout": "1m" - }, - data_autocomplete_rules: { - query: {} - } - }); - api.addEndpointDescription('_percolate', { - methods: ['GET', 'POST'], - priority: 10, // to override doc - patterns: [ - "{indices}/{type}/_percolate" - ], - url_params: { - preference: ["_primary", "_primary_first", "_local", "_only_node:xyz", "_prefer_node:xyz", "_shards:2,3"], - routing: "", - ignore_unavailable: ["true", "false"], - percolate_format: ["ids"] - }, - data_autocomplete_rules: { - doc: {}, - query: {}, - filter: {}, - size: 10, - track_scores: { __one_of: [true, false] }, - sort: "_score", - aggs: {}, - highlight: {} - } - }); - api.addEndpointDescription('_percolate_id', { - methods: ['GET', 'POST'], - patterns: [ - "{indices}/{type}/{id}/_percolate" - ], - url_params: { - routing: "", - ignore_unavailable: ["true", "false"], - percolate_format: ["ids"], - percolate_index: "{index}", - percolate_type: "{type}", - percolate_routing: "", - percolate_preference: ["_primary", "_primary_first", "_local", "_only_node:xyz", "_prefer_node:xyz", "_shards:2,3"], - version: 1, - version_type: ["external", "internal"] - }, - data_autocomplete_rules: { - query: {}, - filter: {}, - size: 10, - track_scores: { __one_of: [true, false] }, - sort: "_score", - aggs: {}, - highlight: {} - } - }); - api.addEndpointDescription('_percolate_count', { - methods: ['GET', 'POST'], - patterns: [ - "{indices}/{type}/_percolate/count" - ], - url_params: { - preference: ["_primary", "_primary_first", "_local", "_only_node:xyz", "_prefer_node:xyz", "_shards:2,3"], - routing: "", - ignore_unavailable: ["true", "false"], - percolate_format: ["ids"] - }, - data_autocomplete_rules: { - doc: {}, - query: {}, - filter: {} - } - }); -} diff --git a/src/core_plugins/console/api_server/es_5_0/query.js b/src/core_plugins/console/api_server/es_5_0/query.js deleted file mode 100644 index c897dcd5052bbd..00000000000000 --- a/src/core_plugins/console/api_server/es_5_0/query.js +++ /dev/null @@ -1,624 +0,0 @@ -let _ = require("lodash"); - -var SPAN_QUERIES = { - // TODO add one_of for objects - span_first: { - __scope_link: '.span_first' - }, - span_near: { - __scope_link: '.span_near' - }, - span_or: { - __scope_link: '.span_or' - }, - span_not: { - __scope_link: '.span_not' - }, - span_term: { - __scope_link: '.span_term' - }, - span_containing: { - __scope_link: '.span_containing' - }, - span_within: { - __scope_link: '.span_within' - } -}; - -var DECAY_FUNC_DESC = { - __template: { - "FIELD": { - "origin": "", - "scale": "" - } - }, - "{field}": { - "origin": "", - "scale": "", - "offset": "", - "decay": 0.5 - } - }, - SCORING_FUNCS = { - "script_score": { - __template: { - "script": "_score * doc['f'].value" - }, - "script": { - //populated by a global rule - } - }, - "boost_factor": 2.0, - "random_score": { - "seed": 314159265359 - }, - "linear": DECAY_FUNC_DESC, - "exp": DECAY_FUNC_DESC, - "gauss": DECAY_FUNC_DESC, - "field_value_factor": { - __template: { - "field": "" - }, - "field": "{field}", - "factor": 1.2, - "modifier": { - __one_of: ["none", "log", "log1p", "log2p", "ln", "ln1p", "ln2p", "square", "sqrt", "reciprocal"] - } - } - }; - -export default function (api) { - api.addGlobalAutocompleteRules('query', { - match: { - __template: { - 'FIELD': 'TEXT' - }, - '{field}': { - 'query': '', - 'operator': { - __one_of: ['and', 'or'] - }, - 'type': { - __one_of: ['phrase', 'phrase_prefix', 'boolean'] - }, - 'max_expansions': 10, - 'analyzer': '', - 'fuzziness': 1.0, - 'prefix_length': 1, - 'minimum_should_match': 1 - } - }, - match_phrase: { - __template: { - 'FIELD': 'PHRASE' - }, - '{field}': { - query: '', - analyzer: '' - } - }, - match_phrase_prefix: { - __template: { - 'FIELD': 'PREFIX' - }, - '{field}': { - query: '', - analyzer: '', - max_expansions: 10, - prefix_length: 1, - fuzziness: 0.1 - } - }, - multi_match: { - __template: { - 'query': '', - 'fields': [] - }, - query: '', - fields: ['{field}'], - use_dis_max: { - __template: true, - __one_of: [true, false] - }, - tie_breaker: 0.0, - type: { __one_of: ['best_fields', 'most_fields', 'cross_fields', 'phrase', 'phrase_prefix'] } - }, - bool: { - must: [ - { - __scope_link: '.' - } - ], - must_not: [ - { - __scope_link: '.' - } - ], - should: [ - { - __scope_link: '.' - } - ], - filter: { - __scope_link: 'GLOBAL.filter' - }, - minimum_should_match: 1, - boost: 1.0 - }, - boosting: { - positive: { - __scope_link: '.' - }, - negative: { - __scope_link: '.' - }, - negative_boost: 0.2 - }, - ids: { - type: '', - values: [] - }, - constant_score: { - __template: { - filter: {}, - boost: 1.2 - }, - query: {}, - filter: {}, - boost: 1.2 - }, - dis_max: { - __template: { - tie_breaker: 0.7, - boost: 1.2, - queries: [] - }, - tie_breaker: 0.7, - boost: 1.2, - queries: [ - { - __scope_link: '.' - } - ] - }, - field: { - '{field}': { - query: '', - boost: 2.0, - enable_position_increments: { - __template: false, - __one_of: [true, false] - } - } - }, - fuzzy: { - '{field}': { - 'value': '', - 'boost': 1.0, - 'fuzziness': 0.5, - 'prefix_length': 0 - } - }, - has_child: { - __template: { - type: 'TYPE', - query: {} - }, - 'type': '{type}', - 'score_mode': { - __one_of: ['none', 'max', 'sum', 'avg'] - }, - '_scope': '', - 'query': {}, - 'min_children': 1, - 'max_children': 10 - }, - has_parent: { - __template: { - parent_type: 'TYPE', - query: {} - }, - 'parent_type': '{type}', - 'score_mode': { - __one_of: ['none', 'score'] - }, - '_scope': '', - 'query': {} - }, - match_all: {}, - more_like_this: { - __template: { - 'fields': ['FIELD'], - 'like': 'text like this one', - 'min_term_freq': 1, - 'max_query_terms': 12 - }, - fields: ['{field}'], - like: '', - percent_terms_to_match: 0.3, - min_term_freq: 2, - max_query_terms: 25, - stop_words: [''], - min_doc_freq: 5, - max_doc_freq: 100, - min_word_len: 0, - max_word_len: 0, - boost_terms: 1, - boost: 1.0, - analyzer: '', - docs: [{ - _index: "{index}", - _type: "{type}", - _id: "" - }], - ids: [""] - }, - mlt: { - __template: { - 'fields': ['FIELD'], - 'like': 'text like this one', - 'min_term_freq': 1, - 'max_query_terms': 12 - }, - __scope_link: ".more_like_this" - }, - prefix: { - __template: { - 'FIELD': { - 'value': '' - } - }, - '{field}': { - value: '', - boost: 1.0 - } - }, - query_string: { - __template: { - 'default_field': 'FIELD', - 'query': 'this AND that OR thus' - }, - query: '', - default_field: '{field}', - fields: ['{field}'], - default_operator: { - __one_of: ['OR', 'AND'] - }, - analyzer: '', - allow_leading_wildcard: { - __one_of: [true, false] - }, - enable_position_increments: { - __one_of: [true, false] - }, - fuzzy_max_expansions: 50, - fuzziness: 0.5, - fuzzy_prefix_length: 0, - phrase_slop: 0, - boost: 1.0, - analyze_wildcard: { - __one_of: [false, true] - }, - auto_generate_phrase_queries: { - __one_of: [false, true] - }, - minimum_should_match: '20%', - lenient: { - __one_of: [false, true] - }, - use_dis_max: { - __one_of: [true, false] - }, - tie_breaker: 0, - time_zone: "+1:00" - }, - simple_query_string: { - __template: { - query: "", - fields: [] - }, - query: "", - fields: ["{field}"], - default_operator: { __one_of: ["OR", "AND"] }, - analyzer: "", - flags: "OR|AND|PREFIX", - locale: "ROOT", - lenient: { __one_of: [true, false] } - }, - range: { - __template: { - 'FIELD': { - gte: 10, - lte: 20 - } - }, - '{field}': { - __template: { - gte: 10, - lte: 20 - }, - gte: 10, - gt: 10, - lte: 20, - lt: 20, - time_zone: "+1:00", - boost: 1.0, - "format": "dd/MM/yyyy||yyyy" - - } - }, - span_first: { - __template: { - 'match': { - 'span_term': { - 'FIELD': 'VALUE' - } - }, - 'end': 3 - }, - match: SPAN_QUERIES - }, - span_near: { - __template: { - 'clauses': [ - { - span_term: { - 'FIELD': { - 'value': 'VALUE' - } - } - } - ], - slop: 12, - in_order: false - }, - clauses: [ - SPAN_QUERIES - ], - slop: 12, - in_order: { - __one_of: [false, true] - }, - collect_payloads: { - __one_of: [false, true] - } - }, - span_term: { - __template: { - 'FIELD': { - 'value': 'VALUE' - } - }, - '{field}': { - value: '', - boost: 2.0 - } - }, - span_not: { - __template: { - include: { - span_term: { - 'FIELD': { - 'value': 'VALUE' - } - } - }, - exclude: { - span_term: { - 'FIELD': { - 'value': 'VALUE' - } - } - } - }, - include: SPAN_QUERIES, - exclude: SPAN_QUERIES - }, - span_or: { - __template: { - clauses: [ - { - span_term: { - 'FIELD': { - 'value': 'VALUE' - } - } - } - ] - }, - clauses: [ - SPAN_QUERIES - ] - }, - span_containing: { - __template: { - little: { - span_term: { - 'FIELD': { - 'value': 'VALUE' - } - } - }, - big: { - span_near: { - 'clauses': [ - { - span_term: { - 'FIELD': { - 'value': 'VALUE' - } - } - }, - { - span_term: { - 'FIELD': { - 'value': 'VALUE' - } - } - } - ], - "slop": 5, - "in_order": false - } - } - }, - little: SPAN_QUERIES, - big: SPAN_QUERIES - }, - span_within: { - __template: { - little: { - span_term: { - 'FIELD': { - 'value': 'VALUE' - } - } - }, - big: { - span_near: { - 'clauses': [ - { - span_term: { - 'FIELD': { - 'value': 'VALUE' - } - } - }, - { - span_term: { - 'FIELD': { - 'value': 'VALUE' - } - } - } - ], - "slop": 5, - "in_order": false - } - } - }, - little: SPAN_QUERIES, - big: SPAN_QUERIES - }, - term: { - __template: { - 'FIELD': { - value: 'VALUE' - } - }, - '{field}': { - value: '', - boost: 2.0 - } - }, - terms: { - __template: { - 'FIELD': ['VALUE1', 'VALUE2'] - }, - '{field}': [''] - }, - wildcard: { - __template: { - 'FIELD': { - value: 'VALUE' - } - }, - '{field}': { - value: '', - boost: 2.0 - } - }, - nested: { - __template: { - path: 'path_to_nested_doc', - query: {} - }, - path: '', - query: {}, - score_mode: { - __one_of: ['avg', 'total', 'max', 'none'] - } - }, - custom_filters_score: { - __template: { - query: {}, - filters: [ - { - filter: {} - } - ] - }, - query: {}, - filters: [ - { - filter: {}, - boost: 2.0, - script: { - //populated by a global rule - } - } - ], - score_mode: { - __one_of: ['first', 'min', 'max', 'total', 'avg', 'multiply'] - }, - max_boost: 2.0, - params: {}, - lang: '' - }, - indices: { - __template: { - indices: ['INDEX1', 'INDEX2'], - query: {} - }, - indices: ['{index}'], - query: {}, - no_match_query: { - __scope_link: '.' - } - }, - geo_shape: { - __template: { - location: {}, - relation: 'within' - }, - __scope_link: '.filter.geo_shape' - }, - // js hint gets confused here - /* jshint -W015 */ - function_score: _.defaults({ - __template: { - query: {}, - functions: [ - {} - ] - }, - query: {}, - functions: [ - _.defaults( - { - filter: {}, - weight: 1.0 - }, - SCORING_FUNCS - ) - ], - boost: 1.0, - boost_mode: { __one_of: ["multiply", "replace", "sum", "avg", "max", "min"] }, - score_mode: { __one_of: ["multiply", "sum", "first", "avg", "max", "min"] }, - max_boost: 10, - min_score: 1.0 - }, - SCORING_FUNCS - ), - script: { - __template: { - "script": "_score * doc['f'].value" - }, - script: { - //populated by a global rule - } - }, - - - }); -} diff --git a/src/core_plugins/console/api_server/es_5_0/search.js b/src/core_plugins/console/api_server/es_5_0/search.js deleted file mode 100644 index 9ffb8eeab20223..00000000000000 --- a/src/core_plugins/console/api_server/es_5_0/search.js +++ /dev/null @@ -1,254 +0,0 @@ -export default function (api) { - api.addEndpointDescription('_search', { - methods: ['GET', 'POST'], - priority: 10, // collides with get doc by id - patterns: [ - '{indices}/{types}/_search', - '{indices}/_search', - '_search' - ], - url_params: { - q: '', - df: '', - analyzer: '', - default_operator: ['AND', 'OR'], - explain: '__flag__', - _source: '', - _source_includes: '', - _source_excludes: '', - stored_fields: [], - sort: '', - track_scores: '__flag__', - timeout: 1, - from: 0, - size: 10, - search_type: ['dfs_query_then_fetch', 'query_then_fetch', 'query_and_fetch'], - terminate_after: 10, - analyze_wildcard: '__flag__', - preference: ['_primary', '_primary_first', '_local', '_only_node:xyz', '_prefer_node:xyz', '_shards:2,3'], - scroll: '5m', - scroll_id: '', - routing: '', - request_cache: ['true', 'false'] - }, - data_autocomplete_rules: { - query: { - // populated by a global rule - }, - aggs: { - __template: { - 'NAME': { - 'AGG_TYPE': {} - } - } - }, - - post_filter: { - __scope_link: 'GLOBAL.filter' - }, - size: { - __template: 20 - }, - from: 0, - sort: { - __template: [ - { - 'FIELD': { - 'order': 'desc' - } - } - ], - __any_of: [ - { - '{field}': { - 'order': { - __one_of: ['desc', 'asc'] - }, - missing: { - __one_of: ['_last', '_first'] - }, - mode: { - __one_of: ['min', 'max', 'avg', 'sum'] - }, - nested_path: '', - nested_filter: { - __scope_link: 'GLOBAL.filter' - } - } - }, - '{field}', - '_score', - { - '_geo_distance': { - __template: { - 'FIELD': { - lat: 40, - lon: -70 - }, - order: 'asc' - }, - '{field}': { - __one_of: [ - { - __template: { - lat: 40, - lon: -70 - }, - lat: 40, - lon: -70 - }, - [ - { - __template: { - lat: 40, - lon: -70 - }, - lat: 40, - lon: -70 - } - ], - [''], - '' - ] - }, - distance_type: { __one_of: ['sloppy_arc', 'arc', 'plane'] }, - sort_mode: { __one_of: ['min', 'max', 'avg'] }, - order: { __one_of: ['asc', 'desc'] }, - unit: 'km' - } - } - ] - }, - stored_fields: ['{field}'], - docvalue_fields: ['{field}'], - script_fields: { - __template: { - 'FIELD': { - 'script': { - // populated by a global rule - } - } - }, - '*': { - __scope_link: 'GLOBAL.script' - } - }, - partial_fields: { - __template: { - 'NAME': { - include: [] - } - }, - '*': { - include: [], - exclude: [] - } - }, - highlight: { - // populated by a global rule - }, - _source: { - __one_of: [ - '{field}', - ['{field}'], - { - 'includes': { - __one_of: [ - '{field}', - ['{field}'] - ] - }, - 'excludes': { - __one_of: [ - '{field}', - ['{field}'] - ] - } - } - ] - }, - explain: { - __one_of: [true, false] - }, - stats: [''], - timeout: '1s', - version: { __one_of: [true, false] } - } - }); - - api.addEndpointDescription('_search_template', { - methods: ['GET'], - patterns: [ - '{indices}/{types}/_search/template', - '{indices}/_search/template', - '_search/template' - ], - data_autocomplete_rules: { - 'template': { - __one_of: [ - { __scope_link: '_search' }, - { __scope_link: 'GLOBAL.script' } - ] - }, - 'params': {} - } - }); - - api.addEndpointDescription('_render_search_template', { - methods: ['GET'], - patterns: [ - '_render/template' - ], - data_autocomplete_rules: { - __one_of: [ - { 'inline': { __scope_link: '_search' } }, - { __scope_link: 'GLOBAL.script' } - ], - 'params': {} - } - }); - - api.addEndpointDescription('_render_search_template_with_id', { - methods: ['GET'], - patterns: [ - '_render/template/{id}' - ], - data_autocomplete_rules: { - 'params': {} - } - }); - - api.addEndpointDescription('_get_delete_search_template', { - methods: ['GET', 'DELETE'], - patterns: [ - '_search/template/{id}' - ] - }); - - api.addEndpointDescription('_put_search_template', { - methods: ['PUT'], - patterns: [ - '_search/template/{id}' - ], - data_autocomplete_rules: { - 'template': { - __scope_link: '_search' - } - } - }); - - api.addEndpointDescription('_search_shards', { - methods: ['GET'], - priority: 10, // collides with get doc by id - patterns: [ - '{indices}/{types}/_search_shards', - '{indices}/_search_shards', - '_search_shards' - ], - url_params: { - preference: ['_primary', '_primary_first', '_local', '_only_node:xyz', '_prefer_node:xyz', '_shards:2,3'], - routing: '', - local: '__flag__' - } - }); -} diff --git a/src/core_plugins/console/api_server/es_6_0.js b/src/core_plugins/console/api_server/es_6_0.js new file mode 100644 index 00000000000000..62bf0a9a383616 --- /dev/null +++ b/src/core_plugins/console/api_server/es_6_0.js @@ -0,0 +1,42 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Api from './api'; +import { getSpec } from './spec'; +const ES_6_0 = new Api('es_6_0'); +const spec = getSpec(); + +// adding generated specs +Object.keys(spec).forEach(endpoint => { + ES_6_0.addEndpointDescription(endpoint, spec[endpoint]); +}); + +//adding globals and custom API definitions +require('./es_6_0/aliases')(ES_6_0); +require('./es_6_0/aggregations')(ES_6_0); +require('./es_6_0/document')(ES_6_0); +require('./es_6_0/filter')(ES_6_0); +require('./es_6_0/globals')(ES_6_0); +require('./es_6_0/ingest')(ES_6_0); +require('./es_6_0/mappings')(ES_6_0); +require('./es_6_0/query')(ES_6_0); +require('./es_6_0/reindex')(ES_6_0); +require('./es_6_0/search')(ES_6_0); + +export default ES_6_0; diff --git a/src/core_plugins/console/api_server/es_6_0/aggregations.js b/src/core_plugins/console/api_server/es_6_0/aggregations.js new file mode 100644 index 00000000000000..da3c496e665d0a --- /dev/null +++ b/src/core_plugins/console/api_server/es_6_0/aggregations.js @@ -0,0 +1,533 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*eslint camelcase: 0*/ +const significantTermsArgs = { + __template: { + field: '', + }, + field: '{field}', + size: 10, + shard_size: 10, + shard_min_doc_count: 10, + min_doc_count: 10, + include: { __one_of: ['*', { pattern: '', flags: '' }] }, + exclude: { __one_of: ['*', { pattern: '', flags: '' }] }, + execution_hint: { + __one_of: ['map', 'global_ordinals', 'global_ordinals_hash'], + }, + background_filter: { + __scope_link: 'GLOBAL.filter', + }, + mutual_information: { + include_negatives: { __one_of: [true, false] }, + }, + chi_square: { + include_negatives: { __one_of: [true, false] }, + background_is_superset: { __one_of: [true, false] }, + }, + percentage: {}, + gnd: { + background_is_superset: { __one_of: [true, false] }, + }, + script_heuristic: { + __template: { + script: '_subset_freq/(_superset_freq - _subset_freq + 1)', + }, + script: { + // populated by a global rule + }, + }, +}; +const simple_metric = { + __template: { field: '' }, + field: '{field}', + missing: 0, + script: { + // populated by a global rule + }, +}; +const field_metric = { + __template: { field: '' }, + field: '{field}', +}; + +const gap_policy = { + __one_of: ['skip', 'insert_zeros'], +}; +const simple_pipeline = { + __template: { + buckets_path: '', + }, + buckets_path: '', + format: '', + gap_policy: gap_policy, +}; +const rules = { + '*': { + aggs: { + __template: { + NAME: { + AGG_TYPE: {}, + }, + }, + }, + adjacency_matrix: { + filters: {} + }, + diversified_sampler: { + shard_size: '', + field: '' + }, + min: simple_metric, + max: simple_metric, + avg: simple_metric, + sum: simple_metric, + stats: simple_metric, + extended_stats: simple_metric, + value_count: { + __template: { + field: '', + }, + field: '{field}', + script: { + // populated by a global rule + }, + }, + global: {}, + filter: {}, + filters: { + __template: { + filters: { + NAME: {}, + }, + }, + filters: { + '*': { __scope_link: 'GLOBAL.filter' }, + }, + other_bucket: { __one_of: [true, false] }, + other_bucket_key: '', + }, + missing: field_metric, + nested: { + __template: { + path: '', + }, + path: '', + }, + reverse_nested: { + __template: { + path: '', + }, + path: '', + }, + terms: { + __template: { + field: '', + size: 10, + }, + field: '{field}', + size: 10, + shard_size: 10, + order: { + __template: { + _term: 'asc', + }, + _term: { __one_of: ['asc', 'desc'] }, + _count: { __one_of: ['asc', 'desc'] }, + '*': { __one_of: ['asc', 'desc'] }, + }, + min_doc_count: 10, + script: { + // populated by a global rule + }, + include: '.*', + exclude: '.*', + execution_hint: { + __one_of: [ + 'map', + 'global_ordinals', + 'global_ordinals_hash', + 'global_ordinals_low_cardinality', + ], + }, + show_term_doc_count_error: { __one_of: [true, false] }, + collect_mode: { __one_of: ['depth_first', 'breadth_first'] }, + missing: '', + }, + significant_text: { + ...significantTermsArgs, + filter_duplicate_text: '__flag__' + }, + significant_terms: significantTermsArgs, + range: { + __template: { + field: '', + ranges: [{ from: 50, to: 100 }], + }, + field: '{field}', + ranges: [{ to: 50, from: 100, key: '' }], + keyed: { __one_of: [true, false] }, + script: { + // populated by a global rule + }, + }, + date_range: { + __template: { + field: '', + ranges: [{ from: 'now-10d/d', to: 'now' }], + }, + field: '{field}', + format: 'MM-yyy', + ranges: [{ to: '', from: '', key: '' }], + keyed: { __one_of: [true, false] }, + script: { + // populated by a global rule + }, + }, + ip_range: { + __template: { + field: '', + ranges: [{ from: '10.0.0.5', to: '10.0.0.10' }], + }, + field: '{field}', + format: 'MM-yyy', + ranges: [{ to: '', from: '', key: '', mask: '10.0.0.127/25' }], + keyed: { __one_of: [true, false] }, + script: { + // populated by a global rule + }, + }, + histogram: { + __template: { + field: 'price', + interval: 50, + }, + field: '{field}', + interval: 50, + extended_bounds: { + __template: { + min: 0, + max: 50, + }, + min: 0, + max: 50, + }, + min_doc_count: 0, + order: { + __template: { + _key: 'asc', + }, + _key: { __one_of: ['asc', 'desc'] }, + _count: { __one_of: ['asc', 'desc'] }, + '*': { __one_of: ['asc', 'desc'] }, + }, + keyed: { __one_of: [true, false] }, + missing: 0, + }, + date_histogram: { + __template: { + field: 'date', + interval: 'month', + }, + field: '{field}', + interval: { + __one_of: [ + 'year', + 'quarter', + 'week', + 'day', + 'hour', + 'minute', + 'second', + ], + }, + min_doc_count: 0, + extended_bounds: { + __template: { + min: 'now/d', + max: 'now/d', + }, + min: 'now/d', + max: 'now/d', + }, + order: { + __template: { + _key: 'asc', + }, + _key: { __one_of: ['asc', 'desc'] }, + _count: { __one_of: ['asc', 'desc'] }, + '*': { __one_of: ['asc', 'desc'] }, + }, + keyed: { __one_of: [true, false] }, + pre_zone: '-01:00', + post_zone: '-01:00', + pre_zone_adjust_large_interval: { __one_of: [true, false] }, + factor: 1000, + pre_offset: '1d', + post_offset: '1d', + format: 'yyyy-MM-dd', + time_zone: '00:00', + missing: '', + }, + geo_distance: { + __template: { + field: 'location', + origin: { lat: 52.376, lon: 4.894 }, + ranges: [{ from: 100, to: 300 }], + }, + field: '{field}', + origin: { lat: 0.0, lon: 0.0 }, + unit: { __one_of: ['mi', 'km', 'in', 'yd', 'm', 'cm', 'mm'] }, + ranges: [{ from: 50, to: 100 }], + distance_type: { __one_of: ['arc', 'sloppy_arc', 'plane'] }, + }, + geohash_grid: { + __template: { + field: '', + precision: 3, + }, + field: '{field}', + precision: { __one_of: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] }, + size: 10, + shard_size: 10, + }, + composite: { + __template: { + sources: [ + { + NAME: { + AGG_TYPE: {}, + }, + }, + ], + }, + sources: [ + { + __scope_link: '.', + __template: { + NAME: { + AGG_TYPE: {}, + }, + }, + }, + ], + size: 10, + after: {}, + }, + percentiles: { + __template: { + field: '', + percents: [1.0, 5.0, 25.0, 50.0, 75.0, 95.0, 99.0], + }, + field: '{field}', + percents: { + __template: [1.0, 5.0, 25.0, 50.0, 75.0, 95.0, 99.0], + // mark type as list + __any_of: [], + }, + script: { + // populated by a global rule + }, + compression: 100, + method: { __one_of: ['hdr', 'tdigest'] }, + missing: 0, + }, + cardinality: { + __template: { + field: '', + }, + precision_threshold: 100, + rehash: true, + script: { + // populated by a global rule + }, + missing: '', + }, + scripted_metric: { + __template: { + init_script: '', + map_script: '', + combine_script: '', + reduce_script: '', + }, + init_script: { + __scope_link: 'GLOBAL.script', + }, + map_script: { + __scope_link: 'GLOBAL.script', + }, + combine_script: { + __scope_link: 'GLOBAL.script', + }, + reduce_script: { + __scope_link: 'GLOBAL.script', + }, + lang: 'groovy', + params: {}, + reduce_params: {}, + }, + geo_bounds: { + __template: { + field: '', + }, + field: '{field}', + wrap_longitude: { __one_of: [true, false] }, + }, + top_hits: { + __template: { + size: 10, + }, + from: 0, + size: 10, + sort: { + __template: [], + __scope_link: 'search.sort', + }, + highlight: {}, + explain: { __one_of: [true, false] }, + _source: { + __template: '', + __scope_link: 'search._source', + }, + script_fields: { + __scope_link: 'search.script_fields', + }, + docvalue_fields: ['{field}'], + version: { __one_of: [true, false] }, + }, + percentile_ranks: { + __template: { + field: '', + values: [10, 15], + }, + field: '{field}', + values: [], + script: { + // populated by a global rule + }, + compression: 100, + method: { __one_of: ['hdr', 'tdigest'] }, + missing: 0, + }, + sampler: { + __template: {}, + field: '{field}', + script: { + // populated by a global rule + }, + shard_size: 100, + max_docs_per_value: 3, + execution_hint: { __one_of: ['map', 'global_ordinals', 'bytes_hash'] }, + }, + children: { + __template: { + type: '', + }, + type: '', + }, + derivative: simple_pipeline, + avg_bucket: simple_pipeline, + max_bucket: simple_pipeline, + min_bucket: simple_pipeline, + stats_bucket: simple_pipeline, + extended_stats_bucket: { + ...simple_pipeline, + sigma: '' + }, + percentiles_bucket: { + ...simple_pipeline, + percents: [] + }, + sum_bucket: simple_pipeline, + moving_avg: { + __template: { + buckets_path: '', + }, + buckets_path: '', + format: '', + gap_policy: gap_policy, + window: 5, + model: { __one_of: ['simple', 'linear', 'ewma', 'holt', 'holt_winters'] }, + settings: { + type: { __one_of: ['add', 'mult'] }, + alpha: 0.5, + beta: 0.5, + gamma: 0.5, + period: 7, + }, + }, + cumulative_sum: { + __template: { + buckets_path: '', + }, + buckets_path: '', + format: '', + }, + serial_diff: { + __template: { + buckets_path: '', + lag: 7, + }, + lag: 7, + gap_policy: gap_policy, + buckets_path: '', + format: '', + }, + bucket_script: { + __template: { + buckets_path: {}, + script: '', + }, + buckets_path: {}, + format: '', + gap_policy: gap_policy, + script: '', + }, + bucket_selector: { + __template: { + buckets_path: {}, + script: '', + }, + buckets_path: {}, + gap_policy: gap_policy, + script: '', + }, + bucket_sort: { + __template: { + sort: [], + }, + sort: ['{field}'], + from: 0, + size: 0, + gap_policy: gap_policy, + }, + matrix_stats: { + __template: { + fields: [], + }, + fields: ['{field}'], + }, + }, +}; + +export default function (api) { + api.addGlobalAutocompleteRules('aggregations', rules); + api.addGlobalAutocompleteRules('aggs', rules); +} diff --git a/src/core_plugins/console/api_server/es_6_0/aliases.js b/src/core_plugins/console/api_server/es_6_0/aliases.js new file mode 100644 index 00000000000000..babc17a25b8c53 --- /dev/null +++ b/src/core_plugins/console/api_server/es_6_0/aliases.js @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export default function (api) { + const aliasRules = { + filter: {}, + routing: '1', + search_routing: '1,2', + index_routing: '1' + }; + api.addGlobalAutocompleteRules('aliases', { + '*': aliasRules + }); +} diff --git a/src/core_plugins/console/api_server/es_6_0/document.js b/src/core_plugins/console/api_server/es_6_0/document.js new file mode 100644 index 00000000000000..d8776f9414bdf9 --- /dev/null +++ b/src/core_plugins/console/api_server/es_6_0/document.js @@ -0,0 +1,79 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export default function (api) { + api.addEndpointDescription('update', { + data_autocomplete_rules: { + 'script': { + // populated by a global rule + }, + 'doc': {}, + 'upsert': {}, + 'scripted_upsert': { __one_of: [true, false] } + } + + }); + + api.addEndpointDescription('put_script', { + methods: ['POST', 'PUT'], + patterns: [ + '_scripts/{lang}/{id}', + '_scripts/{lang}/{id}/_create' + ], + url_components: { + 'lang': [ + 'groovy', + 'expressions' + ] + }, + data_autocomplete_rules: { + 'script': '' + } + }); + + api.addEndpointDescription('termvectors', { + data_autocomplete_rules: { + fields: [ + '{field}' + ], + offsets: { __one_of: [false, true] }, + payloads: { __one_of: [false, true] }, + positions: { __one_of: [false, true] }, + term_statistics: { __one_of: [true, false] }, + field_statistics: { __one_of: [false, true] }, + per_field_analyzer: { + __template: { 'FIELD': '' }, + '{field}': '' + }, + routing: '', + version: 1, + version_type: ['external', 'external_gt', 'external_gte', 'force', 'internal'], + doc: {}, + filter: { // TODO: Exclude from global filter rules + 'max_num_terms': 1, + 'min_term_freq': 1, + 'max_term_freq': 1, + 'min_doc_freq': 1, + 'max_doc_freq': 1, + 'min_word_length': 1, + 'max_word_length': 1 + } + } + }); +} diff --git a/src/core_plugins/console/api_server/es_5_0/filter.js b/src/core_plugins/console/api_server/es_6_0/filter.js similarity index 81% rename from src/core_plugins/console/api_server/es_5_0/filter.js rename to src/core_plugins/console/api_server/es_6_0/filter.js index a66a702a1792b8..710e43845a6430 100644 --- a/src/core_plugins/console/api_server/es_5_0/filter.js +++ b/src/core_plugins/console/api_server/es_6_0/filter.js @@ -1,4 +1,23 @@ -var filters = {}; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const filters = {}; filters.and = { __template: { @@ -253,14 +272,14 @@ filters.range = { lte: 20 } }, - "{field}": { + '{field}': { gte: 1, gt: 1, lte: 20, lt: 20, - time_zone: "+1:00", - "format": "dd/MM/yyyy||yyyy", - execution: { __one_of: ["index", "fielddata"] } + time_zone: '+1:00', + 'format': 'dd/MM/yyyy||yyyy', + execution: { __one_of: ['index', 'fielddata'] } } }; diff --git a/src/core_plugins/console/api_server/es_6_0/globals.js b/src/core_plugins/console/api_server/es_6_0/globals.js new file mode 100644 index 00000000000000..513adbe0fe2fc5 --- /dev/null +++ b/src/core_plugins/console/api_server/es_6_0/globals.js @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const highlightOptions = { + boundary_chars: {}, + boundary_max_scan: 20, + boundary_scanner: { + __one_of: [ 'chars', 'sentence', 'word' ] + }, + boundary_scanner_locale: {}, + encoder: { + __one_of: [ 'default', 'html' ] + }, + force_source: { + __one_of: [ 'false', 'true' ] + }, + fragmenter: { + __one_of: [ 'simple', 'span' ] + }, + highlight_query: { + __scope_link: 'GLOBAL.query' + }, + matched_fields: ['FIELD'], + order: {}, + no_match_size: 0, + number_of_fragments: 5, + phrase_limit: 256, + pre_tags: {}, + post_tags: {}, + require_field_match: { + __one_of: [ 'true', 'false' ] + }, + tags_schema: {} +}; +export default function (api) { + api.addGlobalAutocompleteRules('highlight', { + ...highlightOptions, + fields: { + '{field}': { + fragment_size: 20, + number_of_fragments: 3, + ...highlightOptions + } + } + }); + + api.addGlobalAutocompleteRules('script', { + __template: { + inline: 'SCRIPT' + }, + inline: 'SCRIPT', + file: 'FILE_SCRIPT_NAME', + id: 'SCRIPT_ID', + lang: '', + params: {} + }); +} diff --git a/src/core_plugins/console/api_server/es_5_0/ingest.js b/src/core_plugins/console/api_server/es_6_0/ingest.js similarity index 89% rename from src/core_plugins/console/api_server/es_5_0/ingest.js rename to src/core_plugins/console/api_server/es_6_0/ingest.js index 989b10361eb1dd..2aaa41f9bd7ffb 100644 --- a/src/core_plugins/console/api_server/es_5_0/ingest.js +++ b/src/core_plugins/console/api_server/es_6_0/ingest.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // Based on https://www.elastic.co/guide/en/elasticsearch/reference/master/append-processor.html const appendProcessorDefinition = { append: { @@ -325,9 +344,6 @@ const pipelineDefinition = { version: 123, }; -const simulateUrlParamsDefinition = { - "verbose": "__flag__" -}; export default function (api) { @@ -337,50 +353,21 @@ export default function (api) { data_autocomplete_rules: processorDefinition }); - api.addEndpointDescription('_put_ingest_pipeline', { + api.addEndpointDescription('ingest.put_pipeline', { methods: ['PUT'], patterns: [ - '_ingest/pipeline/{name}' + '_ingest/pipeline/{id}' ], data_autocomplete_rules: pipelineDefinition }); - api.addEndpointDescription('_get_ingest_pipeline', { - methods: ['GET'], - patterns: [ - '_ingest/pipeline/{id}' - ] - }); - api.addEndpointDescription('_delete_ingest_pipeline', { - methods: ['DELETE'], - patterns: [ - '_ingest/pipeline/{id}' - ] - }); - api.addEndpointDescription('_simulate_new_ingest_pipeline', { - methods: ['POST'], - patterns: [ - '_ingest/pipeline/_simulate' - ], - url_params: simulateUrlParamsDefinition, + api.addEndpointDescription('ingest.simulate', { data_autocomplete_rules: { pipeline: pipelineDefinition, docs: [ ] } }); - - api.addEndpointDescription('_simulate_existing_ingest_pipeline', { - methods: ['POST'], - patterns: [ - '_ingest/pipeline/{name}/_simulate' - ], - url_params: simulateUrlParamsDefinition, - data_autocomplete_rules: { - docs: [ - ] - } - }); } diff --git a/src/core_plugins/console/api_server/es_6_0/mappings.js b/src/core_plugins/console/api_server/es_6_0/mappings.js new file mode 100644 index 00000000000000..187dfa2f12f30a --- /dev/null +++ b/src/core_plugins/console/api_server/es_6_0/mappings.js @@ -0,0 +1,254 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const _ = require('lodash'); + +const BOOLEAN = { + __one_of: [true, false], +}; + +export default function (api) { + api.addEndpointDescription('put_mapping', { + priority: 10, // collides with put doc by id + data_autocomplete_rules: { + __template: { + properties: { + FIELD: {}, + }, + }, + _source: { + enabled: BOOLEAN, + }, + _all: { + enabled: BOOLEAN, + }, + _field_names: { + index: BOOLEAN, + }, + _routing: { + required: BOOLEAN, + }, + _index: { + enabled: BOOLEAN, + }, + _parent: { + __template: { + type: '', + }, + type: '{type}', + }, + _timestamp: { + enabled: BOOLEAN, + format: 'YYYY-MM-dd', + default: '', + }, + dynamic_date_formats: ['yyyy-MM-dd'], + date_detection: BOOLEAN, + numeric_detection: BOOLEAN, + properties: { + '*': { + type: { + __one_of: [ + 'text', + 'keyword', + 'float', + 'half_float', + 'scaled_float', + 'double', + 'byte', + 'short', + 'integer', + 'long', + 'date', + 'boolean', + 'binary', + 'object', + 'nested', + 'geo_point', + 'geo_shape', + ], + }, + + // strings + store: BOOLEAN, + index: BOOLEAN, + term_vector: { + __one_of: [ + 'no', + 'yes', + 'with_offsets', + 'with_positions', + 'with_positions_offsets', + ], + }, + boost: 1.0, + null_value: '', + + norms: BOOLEAN, + + index_options: { + __one_of: ['docs', 'freqs', 'positions'], + }, + analyzer: 'standard', + search_analyzer: 'standard', + include_in_all: { + __one_of: [false, true], + }, + ignore_above: 10, + position_increment_gap: 0, + + // numeric + precision_step: 4, + ignore_malformed: BOOLEAN, + scaling_factor: 100, + + // geo_point + lat_lon: { + __one_of: [true, false], + }, + geohash: { + __one_of: [true, false], + }, + geohash_precision: '1m', + geohash_prefix: { + __one_of: [true, false], + }, + validate: { + __one_of: [true, false], + }, + validate_lat: { + __one_of: [true, false], + }, + validate_lon: { + __one_of: [true, false], + }, + normalize: { + __one_of: [true, false], + }, + normalize_lat: { + __one_of: [true, false], + }, + normalize_lon: { + __one_of: [true, false], + }, + + // geo_shape + tree: { + __one_of: ['geohash', 'quadtree'], + }, + precision: '5km', + tree_levels: 12, + distance_error_pct: 0.025, + orientation: 'ccw', + + // dates + format: { + __one_of: _.flatten([ + _.map( + [ + 'date', + 'date_time', + 'date_time_no_millis', + 'ordinal_date', + 'ordinal_date_time', + 'ordinal_date_time_no_millis', + 'time', + 'time_no_millis', + 't_time', + 't_time_no_millis', + 'week_date', + 'week_date_time', + 'week_date_time_no_millis', + ], + function (s) { + return ['basic_' + s, 'strict_' + s]; + } + ), + [ + 'date', + 'date_hour', + 'date_hour_minute', + 'date_hour_minute_second', + 'date_hour_minute_second_fraction', + 'date_hour_minute_second_millis', + 'date_optional_time', + 'date_time', + 'date_time_no_millis', + 'hour', + 'hour_minute', + 'hour_minute_second', + 'hour_minute_second_fraction', + 'hour_minute_second_millis', + 'ordinal_date', + 'ordinal_date_time', + 'ordinal_date_time_no_millis', + 'time', + 'time_no_millis', + 't_time', + 't_time_no_millis', + 'week_date', + 'week_date_time', + 'weekDateTimeNoMillis', + 'week_year', + 'weekyearWeek', + 'weekyearWeekDay', + 'year', + 'year_month', + 'year_month_day', + 'epoch_millis', + 'epoch_second', + ], + ]), + }, + + fielddata: { + filter: { + regex: '', + frequency: { + min: 0.001, + max: 0.1, + min_segment_size: 500, + }, + }, + }, + similarity: { + __one_of: ['default', 'BM25'], + }, + + // objects + properties: { + __scope_link: 'put_mapping.{type}.properties', + }, + + // multi_field + fields: { + '*': { + __scope_link: 'put_mapping.type.properties.field', + }, + }, + copy_to: { __one_of: ['{field}', ['{field}']] }, + + // nested + include_in_parent: BOOLEAN, + include_in_root: BOOLEAN, + }, + }, + }, + }); +} diff --git a/src/core_plugins/console/api_server/es_6_0/query/dsl.js b/src/core_plugins/console/api_server/es_6_0/query/dsl.js new file mode 100644 index 00000000000000..150234950f4a53 --- /dev/null +++ b/src/core_plugins/console/api_server/es_6_0/query/dsl.js @@ -0,0 +1,708 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import _ from 'lodash'; +import { + spanFirstTemplate, + spanNearTemplate, + spanOrTemplate, + spanNotTemplate, + spanTermTemplate, + spanContainingTemplate, + spanWithinTemplate, + wildcardTemplate, + fuzzyTemplate, + prefixTemplate, + rangeTemplate, + regexpTemplate +} from './templates'; +const matchOptions = { + cutoff_frequency: 0.001, + query: '', + operator: { + __one_of: ['and', 'or'], + }, + zero_terms_query: { + __one_of: ['none', 'all'], + }, + max_expansions: 10, + analyzer: '', + boost: 1.0, + lenient: { + __one_of: ['true', 'false'], + }, + fuzzy_transpositions: { + __one_of: ['true', 'false'], + }, + auto_generate_synonyms_phrase_query: { + __one_of: ['true', 'false'], + }, + fuzziness: 1.0, + prefix_length: 1, + minimum_should_match: 1, +}; +const innerHits = { + docvalue_fields: ['FIELD'], + from: {}, + size: {}, + sort: {}, + name: {}, + highlight: {}, + _source: { + __one_of: ['true', 'false'], + }, + explain: { + __one_of: ['true', 'false'], + }, + script_fields: { + __template: { + FIELD: { + script: {}, + }, + }, + '{field}': { + script: {}, + }, + }, + version: { + __one_of: ['true', 'false'], + }, +}; +const SPAN_QUERIES_NO_FIELD_MASK = { + // TODO add one_of for objects + span_first: { + __template: spanFirstTemplate, + __scope_link: '.span_first', + }, + span_near: { + __template: spanNearTemplate, + __scope_link: '.span_near', + }, + span_or: { + __template: spanOrTemplate, + __scope_link: '.span_or', + }, + span_not: { + __template: spanNotTemplate, + __scope_link: '.span_not', + }, + span_term: { + __template: spanTermTemplate, + __scope_link: '.span_term', + }, + span_containing: { + __template: spanContainingTemplate, + __scope_link: '.span_containing', + }, + span_within: { + __template: spanWithinTemplate, + __scope_link: '.span_within', + }, +}; +const SPAN_QUERIES = { + ...SPAN_QUERIES_NO_FIELD_MASK, + field_masking_span: { + __template: { + query: { + SPAN_QUERY: {} + } + }, + query: SPAN_QUERIES_NO_FIELD_MASK, + field: '' + } +}; + +const SPAN_MULTI_QUERIES = { + wildcard: { + __template: wildcardTemplate, + __scope_link: '.wildcard' + }, + fuzzy: { + __template: fuzzyTemplate, + __scope_link: '.fuzzy' + }, + prefix: { + __template: prefixTemplate, + __scope_link: '.prefix' + }, + range: { + __template: rangeTemplate, + __scope_link: '.range' + }, + regexp: { + __template: regexpTemplate, + __scope_link: '.regexp' + } +}; + +const DECAY_FUNC_DESC = { + __template: { + FIELD: { + origin: '', + scale: '', + }, + }, + '{field}': { + origin: '', + scale: '', + offset: '', + decay: 0.5, + }, +}; +const SCORING_FUNCS = { + script_score: { + __template: { + script: '_score * doc[\'f\'].value', + }, + script: { + //populated by a global rule + }, + }, + boost_factor: 2.0, + random_score: { + seed: 314159265359, + }, + linear: DECAY_FUNC_DESC, + exp: DECAY_FUNC_DESC, + gauss: DECAY_FUNC_DESC, + field_value_factor: { + __template: { + field: '', + }, + field: '{field}', + factor: 1.2, + modifier: { + __one_of: [ + 'none', + 'log', + 'log1p', + 'log2p', + 'ln', + 'ln1p', + 'ln2p', + 'square', + 'sqrt', + 'reciprocal', + ], + }, + }, +}; + +export function queryDsl(api) { + api.addGlobalAutocompleteRules('query', { + match: { + __template: { + FIELD: 'TEXT', + }, + '{field}': { + type: { + __one_of: ['phrase', 'phrase_prefix', 'boolean'], + }, + ...matchOptions, + }, + }, + match_phrase: { + __template: { + FIELD: 'PHRASE', + }, + '{field}': { + query: '', + analyzer: '', + slop: 1, + }, + }, + match_phrase_prefix: { + __template: { + FIELD: 'PREFIX', + }, + '{field}': { + query: '', + analyzer: '', + max_expansions: 10, + prefix_length: 1, + fuzziness: 0.1, + }, + }, + regexp: { + __template: regexpTemplate, + '{field}': { + value: '', + flags: { + __one_of: [ + 'ALL', + 'ANYSTRING', + 'COMPLEMENT', + 'EMPTY', + 'INTERSECTION', + 'INTERVAL', + 'NONE', + ], + }, + max_determinized_states: 10000, + }, + }, + multi_match: { + __template: { + query: '', + fields: [], + }, + ...matchOptions, + fields: ['{field}'], + use_dis_max: { + __template: true, + __one_of: [true, false], + }, + tie_breaker: 0.0, + type: { + __one_of: [ + 'best_fields', + 'most_fields', + 'cross_fields', + 'phrase', + 'phrase_prefix', + ], + }, + }, + bool: { + must: [ + { + __scope_link: '.', + }, + ], + must_not: [ + { + __scope_link: '.', + }, + ], + should: [ + { + __scope_link: '.', + }, + ], + filter: { + __scope_link: 'GLOBAL.filter', + }, + minimum_should_match: 1, + boost: 1.0, + }, + boosting: { + positive: { + __scope_link: '.', + }, + negative: { + __scope_link: '.', + }, + negative_boost: 0.2, + }, + ids: { + type: '', + values: [], + }, + constant_score: { + __template: { + filter: {}, + boost: 1.2, + }, + query: {}, + filter: {}, + boost: 1.2, + }, + dis_max: { + __template: { + tie_breaker: 0.7, + boost: 1.2, + queries: [], + }, + tie_breaker: 0.7, + boost: 1.2, + queries: [ + { + __scope_link: '.', + }, + ], + }, + exists: { + field: '', + }, + field: { + '{field}': { + query: '', + boost: 2.0, + enable_position_increments: { + __template: false, + __one_of: [true, false], + }, + }, + }, + fuzzy: { + __template: fuzzyTemplate, + '{field}': { + value: '', + boost: 1.0, + fuzziness: 0.5, + prefix_length: 0, + }, + }, + has_child: { + __template: { + type: 'TYPE', + query: {}, + }, + inner_hits: { ...innerHits }, + type: '{type}', + score_mode: { + __one_of: ['none', 'max', 'sum', 'avg'], + }, + _scope: '', + query: {}, + min_children: 1, + max_children: 10, + }, + has_parent: { + __template: { + parent_type: 'TYPE', + query: {}, + }, + parent_type: '{type}', + score_mode: { + __one_of: ['none', 'score'], + }, + _scope: '', + query: {}, + }, + match_all: {}, + more_like_this: { + __template: { + fields: ['FIELD'], + like: 'text like this one', + min_term_freq: 1, + max_query_terms: 12, + }, + fields: ['{field}'], + like: '', + percent_terms_to_match: 0.3, + min_term_freq: 2, + max_query_terms: 25, + stop_words: [''], + min_doc_freq: 5, + max_doc_freq: 100, + min_word_len: 0, + max_word_len: 0, + boost_terms: 1, + boost: 1.0, + analyzer: '', + docs: [ + { + _index: '{index}', + _type: '{type}', + _id: '', + }, + ], + ids: [''], + }, + mlt: { + __template: { + fields: ['FIELD'], + like: 'text like this one', + min_term_freq: 1, + max_query_terms: 12, + }, + __scope_link: '.more_like_this', + }, + prefix: { + __template: prefixTemplate, + '{field}': { + value: '', + boost: 1.0, + }, + }, + query_string: { + __template: { + default_field: 'FIELD', + query: 'this AND that OR thus', + }, + query: '', + default_field: '{field}', + fields: ['{field}'], + default_operator: { + __one_of: ['OR', 'AND'], + }, + analyzer: '', + allow_leading_wildcard: { + __one_of: [true, false], + }, + enable_position_increments: { + __one_of: [true, false], + }, + fuzzy_max_expansions: 50, + fuzziness: 0.5, + fuzzy_prefix_length: 0, + phrase_slop: 0, + boost: 1.0, + analyze_wildcard: { + __one_of: [false, true], + }, + auto_generate_phrase_queries: { + __one_of: [false, true], + }, + minimum_should_match: '20%', + lenient: { + __one_of: [false, true], + }, + use_dis_max: { + __one_of: [true, false], + }, + tie_breaker: 0, + time_zone: '+1:00', + }, + simple_query_string: { + __template: { + query: '', + fields: [], + }, + query: '', + fields: ['{field}'], + default_operator: { __one_of: ['OR', 'AND'] }, + analyzer: '', + flags: 'OR|AND|PREFIX', + locale: 'ROOT', + lenient: { __one_of: [true, false] }, + }, + range: { + __template: rangeTemplate, + '{field}': { + __template: { + gte: 10, + lte: 20, + }, + gte: 10, + gt: 10, + lte: 20, + lt: 20, + time_zone: '+1:00', + boost: 1.0, + format: 'dd/MM/yyyy||yyyy', + }, + }, + span_first: { + __template: spanFirstTemplate, + match: SPAN_QUERIES, + }, + span_multi: { + __template: { + match: { + MULTI_TERM_QUERY: {} + } + }, + match: SPAN_MULTI_QUERIES + }, + span_near: { + __template: spanNearTemplate, + clauses: [SPAN_QUERIES], + slop: 12, + in_order: { + __one_of: [false, true], + }, + collect_payloads: { + __one_of: [false, true], + }, + }, + span_term: { + __template: spanTermTemplate, + '{field}': { + value: '', + boost: 2.0, + }, + }, + span_not: { + __template: spanNotTemplate, + include: SPAN_QUERIES, + exclude: SPAN_QUERIES, + }, + span_or: { + __template: spanOrTemplate, + clauses: [SPAN_QUERIES], + }, + span_containing: { + __template: spanContainingTemplate, + little: SPAN_QUERIES, + big: SPAN_QUERIES, + }, + span_within: { + __template: spanWithinTemplate, + little: SPAN_QUERIES, + big: SPAN_QUERIES, + }, + term: { + __template: { + FIELD: { + value: 'VALUE', + }, + }, + '{field}': { + value: '', + boost: 2.0, + }, + }, + terms: { + __template: { + FIELD: ['VALUE1', 'VALUE2'], + }, + '{field}': [''], + }, + wildcard: { + __template: wildcardTemplate, + '{field}': { + value: '', + boost: 2.0, + }, + }, + nested: { + __template: { + path: 'path_to_nested_doc', + query: {}, + }, + inner_hits: { ...innerHits }, + path: '', + query: {}, + score_mode: { + __one_of: ['avg', 'total', 'max', 'none'], + }, + }, + percolate: { + __template: { + field: '', + document: {} + }, + field: '', + document: {}, + name: '', + documents: [{}], + document_type: '', + index: '', + type: '', + id: '', + routing: '', + preference: '' + }, + common: { + __template: { + FIELD: { + query: {}, + }, + }, + '{field}': { + query: {}, + cutoff_frequency: 0.001, + minimum_should_match: { + low_freq: {}, + high_freq: {}, + }, + }, + }, + custom_filters_score: { + __template: { + query: {}, + filters: [ + { + filter: {}, + }, + ], + }, + query: {}, + filters: [ + { + filter: {}, + boost: 2.0, + script: { + //populated by a global rule + }, + }, + ], + score_mode: { + __one_of: ['first', 'min', 'max', 'total', 'avg', 'multiply'], + }, + max_boost: 2.0, + params: {}, + lang: '', + }, + indices: { + __template: { + indices: ['INDEX1', 'INDEX2'], + query: {}, + }, + indices: ['{index}'], + query: {}, + no_match_query: { + __scope_link: '.', + }, + }, + geo_shape: { + __template: { + location: {}, + relation: 'within', + }, + __scope_link: '.filter.geo_shape', + }, + // js hint gets confused here + /* jshint -W015 */ + function_score: _.defaults( + { + __template: { + query: {}, + functions: [{}], + }, + query: {}, + functions: [ + _.defaults( + { + filter: {}, + weight: 1.0, + }, + SCORING_FUNCS + ), + ], + boost: 1.0, + boost_mode: { + __one_of: ['multiply', 'replace', 'sum', 'avg', 'max', 'min'], + }, + score_mode: { + __one_of: ['multiply', 'sum', 'first', 'avg', 'max', 'min'], + }, + max_boost: 10, + min_score: 1.0, + }, + SCORING_FUNCS + ), + script: { + __template: { + script: '_score * doc[\'f\'].value', + }, + script: { + //populated by a global rule + }, + }, + wrapper: { + __template: { + query: 'QUERY_BASE64_ENCODED', + }, + query: '' + } + }); +} diff --git a/src/core_plugins/console/api_server/es_6_0/query/index.js b/src/core_plugins/console/api_server/es_6_0/query/index.js new file mode 100644 index 00000000000000..8366478afe1acb --- /dev/null +++ b/src/core_plugins/console/api_server/es_6_0/query/index.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { queryDsl as default } from './dsl'; \ No newline at end of file diff --git a/src/core_plugins/console/api_server/es_6_0/query/templates.js b/src/core_plugins/console/api_server/es_6_0/query/templates.js new file mode 100644 index 00000000000000..9b6311bf5712e4 --- /dev/null +++ b/src/core_plugins/console/api_server/es_6_0/query/templates.js @@ -0,0 +1,156 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const regexpTemplate = { + FIELD: 'REGEXP', +}; +export const fuzzyTemplate = { + FIELD: {}, +}; +export const prefixTemplate = { + FIELD: { + value: '', + }, +}; +export const rangeTemplate = { + FIELD: { + gte: 10, + lte: 20, + }, +}; +export const spanFirstTemplate = { + match: { + span_term: { + FIELD: 'VALUE', + }, + }, + end: 3, +}; +export const spanNearTemplate = { + clauses: [ + { + span_term: { + FIELD: { + value: 'VALUE', + }, + }, + }, + ], + slop: 12, + in_order: false, +}; +export const spanTermTemplate = { + FIELD: { + value: 'VALUE', + }, +}; +export const spanNotTemplate = { + include: { + span_term: { + FIELD: { + value: 'VALUE', + }, + }, + }, + exclude: { + span_term: { + FIELD: { + value: 'VALUE', + }, + }, + }, +}; +export const spanOrTemplate = { + clauses: [ + { + span_term: { + FIELD: { + value: 'VALUE', + }, + }, + }, + ], +}; +export const spanContainingTemplate = { + little: { + span_term: { + FIELD: { + value: 'VALUE', + }, + }, + }, + big: { + span_near: { + clauses: [ + { + span_term: { + FIELD: { + value: 'VALUE', + }, + }, + }, + { + span_term: { + FIELD: { + value: 'VALUE', + }, + }, + }, + ], + slop: 5, + in_order: false, + }, + }, +}; +export const spanWithinTemplate = { + little: { + span_term: { + FIELD: { + value: 'VALUE', + }, + }, + }, + big: { + span_near: { + clauses: [ + { + span_term: { + FIELD: { + value: 'VALUE', + }, + }, + }, + { + span_term: { + FIELD: { + value: 'VALUE', + }, + }, + }, + ], + slop: 5, + in_order: false, + }, + }, +}; +export const wildcardTemplate = { + FIELD: { + value: 'VALUE', + }, +}; diff --git a/src/core_plugins/console/api_server/es_5_0/reindex.js b/src/core_plugins/console/api_server/es_6_0/reindex.js similarity index 55% rename from src/core_plugins/console/api_server/es_5_0/reindex.js rename to src/core_plugins/console/api_server/es_6_0/reindex.js index 6cf57cc54e6dcf..618c1f4dcaf0df 100644 --- a/src/core_plugins/console/api_server/es_5_0/reindex.js +++ b/src/core_plugins/console/api_server/es_6_0/reindex.js @@ -1,18 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function (api) { - api.addEndpointDescription('_post_reindex', { + api.addEndpointDescription('reindex', { methods: [ 'POST' ], patterns: [ '_reindex' ], - url_params: { - refresh: '__flag__', - wait_for_completion: 'true', - wait_for_active_shards: 1, - timeout: '1m', - requests_per_second: 0, - slices: 1 - }, data_autocomplete_rules: { __template: { 'source': {}, @@ -53,5 +64,5 @@ export default function (api) { 'size': 10, 'script': { __scope_link: 'GLOBAL.script' }, } - }) + }); } \ No newline at end of file diff --git a/src/core_plugins/console/api_server/es_6_0/search.js b/src/core_plugins/console/api_server/es_6_0/search.js new file mode 100644 index 00000000000000..646d299b4c1a62 --- /dev/null +++ b/src/core_plugins/console/api_server/es_6_0/search.js @@ -0,0 +1,224 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export default function (api) { + api.addEndpointDescription('search', { + priority: 10, // collides with get doc by id + data_autocomplete_rules: { + query: { + // populated by a global rule + }, + profile: { + __one_of: ['true', 'false'], + }, + aggs: { + __template: { + NAME: { + AGG_TYPE: {}, + }, + }, + }, + + post_filter: { + __scope_link: 'GLOBAL.filter', + }, + size: { + __template: 20, + }, + from: 0, + sort: { + __template: [ + { + FIELD: { + order: 'desc', + }, + }, + ], + __any_of: [ + { + '{field}': { + order: { + __one_of: ['desc', 'asc'], + }, + missing: { + __one_of: ['_last', '_first'], + }, + mode: { + __one_of: ['min', 'max', 'avg', 'sum'], + }, + nested_path: '', + nested_filter: { + __scope_link: 'GLOBAL.filter', + }, + }, + }, + '{field}', + '_score', + { + _geo_distance: { + __template: { + FIELD: { + lat: 40, + lon: -70, + }, + order: 'asc', + }, + '{field}': { + __one_of: [ + { + __template: { + lat: 40, + lon: -70, + }, + lat: 40, + lon: -70, + }, + [ + { + __template: { + lat: 40, + lon: -70, + }, + lat: 40, + lon: -70, + }, + ], + [''], + '', + ], + }, + distance_type: { __one_of: ['sloppy_arc', 'arc', 'plane'] }, + sort_mode: { __one_of: ['min', 'max', 'avg'] }, + order: { __one_of: ['asc', 'desc'] }, + unit: 'km', + }, + }, + ], + }, + stored_fields: ['{field}'], + suggest: { + __template: { + YOUR_SUGGESTION: { + text: 'YOUR TEXT', + term: { + FIELD: 'MESSAGE', + }, + }, + }, + '*': { + include: [], + exclude: [], + }, + }, + docvalue_fields: ['{field}'], + collapse: { + __template: { + 'field': 'FIELD' + } + }, + indices_boost: { + __template: [ + { 'INDEX': 1.0 } + ] + }, + rescore: { + __template: { + 'query': {}, + 'window_size': 50 + } + }, + script_fields: { + __template: { + FIELD: { + script: { + // populated by a global rule + }, + }, + }, + '*': { + __scope_link: 'GLOBAL.script', + }, + }, + partial_fields: { + __template: { + NAME: { + include: [], + }, + }, + '*': { + include: [], + exclude: [], + }, + }, + highlight: { + // populated by a global rule + }, + _source: { + __one_of: [ + '{field}', + ['{field}'], + { + includes: { + __one_of: ['{field}', ['{field}']], + }, + excludes: { + __one_of: ['{field}', ['{field}']], + }, + }, + ], + }, + explain: { + __one_of: [true, false], + }, + stats: [''], + timeout: '1s', + version: { __one_of: [true, false] }, + }, + }); + + api.addEndpointDescription('search_template', { + data_autocomplete_rules: { + template: { + __one_of: [ + { __scope_link: 'search' }, + { __scope_link: 'GLOBAL.script' }, + ], + }, + params: {}, + }, + }); + + api.addEndpointDescription('render_search_template', { + data_autocomplete_rules: { + __one_of: [ + { inline: { __scope_link: 'search' } }, + { __scope_link: 'GLOBAL.script' }, + ], + params: {}, + }, + }); + + api.addEndpointDescription('_search/template/{id}', { + data_autocomplete_rules: { + template: { + __scope_link: 'search', + }, + }, + }); +} diff --git a/src/core_plugins/console/api_server/server.js b/src/core_plugins/console/api_server/server.js index 9782af96071fda..6697dbe4d37a71 100644 --- a/src/core_plugins/console/api_server/server.js +++ b/src/core_plugins/console/api_server/server.js @@ -1,14 +1,33 @@ -let _ = require("lodash"); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ -export function resolveApi(sense_version, apis, reply) { - let result = {}; +import _ from 'lodash'; + +export function resolveApi(senseVersion, apis, reply) { + const result = {}; _.each(apis, function (name) { { // for now we ignore sense_version. might add it in the api name later - let api = require('./' + name); + const api = require('./' + name); result[name] = api.asJson(); } }); - return reply(result).type("application/json"); + return reply(result).type('application/json'); } diff --git a/src/core_plugins/console/api_server/.eslintrc b/src/core_plugins/console/api_server/spec/.eslintrc similarity index 93% rename from src/core_plugins/console/api_server/.eslintrc rename to src/core_plugins/console/api_server/spec/.eslintrc index b0b0dc2b266499..0ef3edb367ed5a 100644 --- a/src/core_plugins/console/api_server/.eslintrc +++ b/src/core_plugins/console/api_server/spec/.eslintrc @@ -1,7 +1,7 @@ --- root: true -extends: '../../../../.eslintrc.js' +extends: '../../../../../.eslintrc.js' rules: block-scoped-var: off diff --git a/src/core_plugins/console/api_server/spec/generated/_common.json b/src/core_plugins/console/api_server/spec/generated/_common.json new file mode 100644 index 00000000000000..0967ef424bce67 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/_common.json @@ -0,0 +1 @@ +{} diff --git a/src/core_plugins/console/api_server/spec/generated/bulk.json b/src/core_plugins/console/api_server/spec/generated/bulk.json index 9ea67c0f272ceb..db286befde772c 100644 --- a/src/core_plugins/console/api_server/spec/generated/bulk.json +++ b/src/core_plugins/console/api_server/spec/generated/bulk.json @@ -1,6 +1,7 @@ { - "_bulk": { + "bulk": { "url_params": { + "include_type_name": "", "wait_for_active_shards": "", "refresh": [ "true", @@ -10,7 +11,6 @@ "routing": "", "timeout": "", "type": "", - "fields": [], "_source": [], "_source_exclude": [], "_source_include": [], @@ -24,6 +24,7 @@ "_bulk", "{indices}/_bulk", "{indices}/{type}/_bulk" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-bulk.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.aliases.json b/src/core_plugins/console/api_server/spec/generated/cat.aliases.json index adc93914452fa8..3e749c4de78520 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.aliases.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.aliases.json @@ -1,5 +1,5 @@ { - "_cat/aliases": { + "cat.aliases": { "url_params": { "format": "", "local": "__flag__", @@ -15,6 +15,7 @@ "patterns": [ "_cat/aliases", "_cat/aliases/{name}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-alias.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.allocation.json b/src/core_plugins/console/api_server/spec/generated/cat.allocation.json index 5f92ce7a315495..9900363b80ee78 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.allocation.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.allocation.json @@ -1,5 +1,5 @@ { - "_cat/allocation": { + "cat.allocation": { "url_params": { "format": "", "bytes": [ @@ -28,6 +28,7 @@ "patterns": [ "_cat/allocation", "_cat/allocation/{nodes}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-allocation.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.count.json b/src/core_plugins/console/api_server/spec/generated/cat.count.json index 443353f853ff5b..392bee6f905991 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.count.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.count.json @@ -1,5 +1,5 @@ { - "_cat/count": { + "cat.count": { "url_params": { "format": "", "local": "__flag__", @@ -15,6 +15,7 @@ "patterns": [ "_cat/count", "_cat/count/{indices}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-count.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.fielddata.json b/src/core_plugins/console/api_server/spec/generated/cat.fielddata.json index 385ac0d7084d4d..970ed974b41a2c 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.fielddata.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.fielddata.json @@ -1,5 +1,5 @@ { - "_cat/fielddata": { + "cat.fielddata": { "url_params": { "format": "", "bytes": [ @@ -29,6 +29,7 @@ "patterns": [ "_cat/fielddata", "_cat/fielddata/{fields}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-fielddata.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.health.json b/src/core_plugins/console/api_server/spec/generated/cat.health.json index bc363251654217..0cc04d2bd75651 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.health.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.health.json @@ -1,5 +1,5 @@ { - "_cat/health": { + "cat.health": { "url_params": { "format": "", "local": "__flag__", @@ -15,6 +15,7 @@ ], "patterns": [ "_cat/health" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-health.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.help.json b/src/core_plugins/console/api_server/spec/generated/cat.help.json index a46b870d8f745f..b58aea9e3f0d51 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.help.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.help.json @@ -1,5 +1,5 @@ { - "_cat": { + "cat.help": { "url_params": { "help": "__flag__", "s": [] @@ -9,6 +9,7 @@ ], "patterns": [ "_cat" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.indices.json b/src/core_plugins/console/api_server/spec/generated/cat.indices.json index e40963ccce84d0..c344b94f52f540 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.indices.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.indices.json @@ -1,5 +1,5 @@ { - "_cat/indices": { + "cat.indices": { "url_params": { "format": "", "bytes": [ @@ -27,6 +27,7 @@ "patterns": [ "_cat/indices", "_cat/indices/{indices}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-indices.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.master.json b/src/core_plugins/console/api_server/spec/generated/cat.master.json index 19e53288b4a5d9..f81936af95856d 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.master.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.master.json @@ -1,5 +1,5 @@ { - "_cat/master": { + "cat.master": { "url_params": { "format": "", "local": "__flag__", @@ -14,6 +14,7 @@ ], "patterns": [ "_cat/master" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-master.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.nodeattrs.json b/src/core_plugins/console/api_server/spec/generated/cat.nodeattrs.json index 10a72c8720d2a8..711f2be480fd46 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.nodeattrs.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.nodeattrs.json @@ -1,5 +1,5 @@ { - "_cat/nodeattrs": { + "cat.nodeattrs": { "url_params": { "format": "", "local": "__flag__", @@ -14,6 +14,7 @@ ], "patterns": [ "_cat/nodeattrs" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-nodeattrs.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.nodes.json b/src/core_plugins/console/api_server/spec/generated/cat.nodes.json index a571292f1f717b..fd15246811f8ba 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.nodes.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.nodes.json @@ -1,5 +1,5 @@ { - "_cat/nodes": { + "cat.nodes": { "url_params": { "format": "", "full_id": "__flag__", @@ -15,6 +15,7 @@ ], "patterns": [ "_cat/nodes" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-nodes.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.pending_tasks.json b/src/core_plugins/console/api_server/spec/generated/cat.pending_tasks.json index bc5603886367b0..ef694ec3827011 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.pending_tasks.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.pending_tasks.json @@ -1,5 +1,5 @@ { - "_cat/pending_tasks": { + "cat.pending_tasks": { "url_params": { "format": "", "local": "__flag__", @@ -14,6 +14,7 @@ ], "patterns": [ "_cat/pending_tasks" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-pending-tasks.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.plugins.json b/src/core_plugins/console/api_server/spec/generated/cat.plugins.json index d0a9af9c85edfb..4b5c8fce2fdf99 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.plugins.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.plugins.json @@ -1,5 +1,5 @@ { - "_cat/plugins": { + "cat.plugins": { "url_params": { "format": "", "local": "__flag__", @@ -14,6 +14,7 @@ ], "patterns": [ "_cat/plugins" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-plugins.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.recovery.json b/src/core_plugins/console/api_server/spec/generated/cat.recovery.json index 5d9c9a1b7a5570..ee8bf0a7910394 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.recovery.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.recovery.json @@ -1,5 +1,5 @@ { - "_cat/recovery": { + "cat.recovery": { "url_params": { "format": "", "bytes": [ @@ -27,6 +27,7 @@ "patterns": [ "_cat/recovery", "_cat/recovery/{indices}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-recovery.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.repositories.json b/src/core_plugins/console/api_server/spec/generated/cat.repositories.json index 648e3887c50de0..3aad8a5ee518f8 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.repositories.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.repositories.json @@ -1,5 +1,5 @@ { - "_cat/repositories": { + "cat.repositories": { "url_params": { "format": "", "local": "__flag__", @@ -14,6 +14,7 @@ ], "patterns": [ "_cat/repositories" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-repositories.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.segments.json b/src/core_plugins/console/api_server/spec/generated/cat.segments.json index b6b49c7fd46874..ffd771e5e4f7f9 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.segments.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.segments.json @@ -1,5 +1,5 @@ { - "_cat/segments": { + "cat.segments": { "url_params": { "format": "", "bytes": [ @@ -26,6 +26,7 @@ "patterns": [ "_cat/segments", "_cat/segments/{indices}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-segments.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.shards.json b/src/core_plugins/console/api_server/spec/generated/cat.shards.json index 396e13ab9c52ac..e0ce5cb1567c1b 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.shards.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.shards.json @@ -1,5 +1,5 @@ { - "_cat/shards": { + "cat.shards": { "url_params": { "format": "", "bytes": [ @@ -28,6 +28,7 @@ "patterns": [ "_cat/shards", "_cat/shards/{indices}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-shards.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.snapshots.json b/src/core_plugins/console/api_server/spec/generated/cat.snapshots.json index 8f6d64a154cb13..dbb6023fcc83b9 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.snapshots.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.snapshots.json @@ -1,5 +1,5 @@ { - "_cat/snapshots": { + "cat.snapshots": { "url_params": { "format": "", "ignore_unavailable": "__flag__", @@ -15,6 +15,7 @@ "patterns": [ "_cat/snapshots", "_cat/snapshots/{repository}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-snapshots.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.tasks.json b/src/core_plugins/console/api_server/spec/generated/cat.tasks.json index 566404ff72057f..ac5e907bd30fe3 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.tasks.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.tasks.json @@ -1,11 +1,10 @@ { - "_cat/tasks": { + "cat.tasks": { "url_params": { "format": "", "node_id": [], "actions": [], "detailed": "__flag__", - "parent_node": "", "parent_task": "", "h": [], "help": "__flag__", @@ -17,6 +16,7 @@ ], "patterns": [ "_cat/tasks" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.templates.json b/src/core_plugins/console/api_server/spec/generated/cat.templates.json index bc4500ee4f7c30..f8c35873aeed1c 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.templates.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.templates.json @@ -1,5 +1,5 @@ { - "_cat/templates": { + "cat.templates": { "url_params": { "format": "", "local": "__flag__", @@ -15,6 +15,7 @@ "patterns": [ "_cat/templates", "_cat/templates/{name}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-templates.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cat.thread_pool.json b/src/core_plugins/console/api_server/spec/generated/cat.thread_pool.json index 0e141dee502277..508f1f2ff5f242 100644 --- a/src/core_plugins/console/api_server/spec/generated/cat.thread_pool.json +++ b/src/core_plugins/console/api_server/spec/generated/cat.thread_pool.json @@ -1,5 +1,5 @@ { - "_cat/thread_pool": { + "cat.thread_pool": { "url_params": { "format": "", "size": [ @@ -23,6 +23,7 @@ "patterns": [ "_cat/thread_pool", "_cat/thread_pool/{thread_pool_patterns}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-thread-pool.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/clear_scroll.json b/src/core_plugins/console/api_server/spec/generated/clear_scroll.json index 3889ada9b841e8..7cc713d0fdc62c 100644 --- a/src/core_plugins/console/api_server/spec/generated/clear_scroll.json +++ b/src/core_plugins/console/api_server/spec/generated/clear_scroll.json @@ -1,12 +1,12 @@ { - "_search/scroll/{scroll_id}": { - "url_params": {}, + "clear_scroll": { "methods": [ "DELETE" ], "patterns": [ "_search/scroll/{scroll_id}", "_search/scroll" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-request-scroll.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cluster.allocation_explain.json b/src/core_plugins/console/api_server/spec/generated/cluster.allocation_explain.json index 68f7fe4c5e9bf3..a44eb2e117a783 100644 --- a/src/core_plugins/console/api_server/spec/generated/cluster.allocation_explain.json +++ b/src/core_plugins/console/api_server/spec/generated/cluster.allocation_explain.json @@ -1,5 +1,5 @@ { - "_cluster/allocation/explain": { + "cluster.allocation_explain": { "url_params": { "include_yes_decisions": "__flag__", "include_disk_info": "__flag__" @@ -10,6 +10,7 @@ ], "patterns": [ "_cluster/allocation/explain" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-allocation-explain.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cluster.get_settings.json b/src/core_plugins/console/api_server/spec/generated/cluster.get_settings.json index 27c526690f2a8f..998e9a953ec9a3 100644 --- a/src/core_plugins/console/api_server/spec/generated/cluster.get_settings.json +++ b/src/core_plugins/console/api_server/spec/generated/cluster.get_settings.json @@ -1,5 +1,5 @@ { - "_cluster/settings": { + "cluster.get_settings": { "url_params": { "flat_settings": "__flag__", "master_timeout": "", @@ -11,6 +11,7 @@ ], "patterns": [ "_cluster/settings" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cluster.health.json b/src/core_plugins/console/api_server/spec/generated/cluster.health.json index e30e4cc58d461a..db1c19443a4969 100644 --- a/src/core_plugins/console/api_server/spec/generated/cluster.health.json +++ b/src/core_plugins/console/api_server/spec/generated/cluster.health.json @@ -1,5 +1,5 @@ { - "_cluster/health": { + "cluster.health": { "url_params": { "level": [ "cluster", @@ -33,6 +33,7 @@ "patterns": [ "_cluster/health", "_cluster/health/{indices}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-health.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cluster.pending_tasks.json b/src/core_plugins/console/api_server/spec/generated/cluster.pending_tasks.json index ad0475afd3850f..0883bf50db2e56 100644 --- a/src/core_plugins/console/api_server/spec/generated/cluster.pending_tasks.json +++ b/src/core_plugins/console/api_server/spec/generated/cluster.pending_tasks.json @@ -1,5 +1,5 @@ { - "_cluster/pending_tasks": { + "cluster.pending_tasks": { "url_params": { "local": "__flag__", "master_timeout": "" @@ -9,6 +9,7 @@ ], "patterns": [ "_cluster/pending_tasks" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-pending.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cluster.put_settings.json b/src/core_plugins/console/api_server/spec/generated/cluster.put_settings.json index adc589fd5defc0..1ce70f64ff0fc3 100644 --- a/src/core_plugins/console/api_server/spec/generated/cluster.put_settings.json +++ b/src/core_plugins/console/api_server/spec/generated/cluster.put_settings.json @@ -1,5 +1,5 @@ { - "_cluster/settings": { + "cluster.put_settings": { "url_params": { "flat_settings": "__flag__", "master_timeout": "", @@ -10,6 +10,7 @@ ], "patterns": [ "_cluster/settings" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-update-settings.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cluster.remote_info.json b/src/core_plugins/console/api_server/spec/generated/cluster.remote_info.json index 6c8f2fb4938128..e7f612eb2adc94 100644 --- a/src/core_plugins/console/api_server/spec/generated/cluster.remote_info.json +++ b/src/core_plugins/console/api_server/spec/generated/cluster.remote_info.json @@ -1,11 +1,11 @@ { - "_remote/info": { - "url_params": {}, + "cluster.remote_info": { "methods": [ "GET" ], "patterns": [ "_remote/info" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-remote-info.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cluster.reroute.json b/src/core_plugins/console/api_server/spec/generated/cluster.reroute.json index 3490ea3321a225..627e1c1335bf4c 100644 --- a/src/core_plugins/console/api_server/spec/generated/cluster.reroute.json +++ b/src/core_plugins/console/api_server/spec/generated/cluster.reroute.json @@ -1,5 +1,5 @@ { - "_cluster/reroute": { + "cluster.reroute": { "url_params": { "dry_run": "__flag__", "explain": "__flag__", @@ -13,6 +13,7 @@ ], "patterns": [ "_cluster/reroute" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-reroute.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cluster.state.json b/src/core_plugins/console/api_server/spec/generated/cluster.state.json index 40954a5f048b5f..23ab8b218d65f8 100644 --- a/src/core_plugins/console/api_server/spec/generated/cluster.state.json +++ b/src/core_plugins/console/api_server/spec/generated/cluster.state.json @@ -1,5 +1,5 @@ { - "_cluster/state": { + "cluster.state": { "url_params": { "local": "__flag__", "master_timeout": "", @@ -33,6 +33,7 @@ "routing_table", "version" ] - } + }, + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-state.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/cluster.stats.json b/src/core_plugins/console/api_server/spec/generated/cluster.stats.json index 111636350482ee..96bf4fb98941cb 100644 --- a/src/core_plugins/console/api_server/spec/generated/cluster.stats.json +++ b/src/core_plugins/console/api_server/spec/generated/cluster.stats.json @@ -1,5 +1,5 @@ { - "_cluster/stats": { + "cluster.stats": { "url_params": { "flat_settings": "__flag__", "timeout": "" @@ -10,6 +10,7 @@ "patterns": [ "_cluster/stats", "_cluster/stats/nodes/{nodes}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-stats.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/count.json b/src/core_plugins/console/api_server/spec/generated/count.json index f60d29a6e79685..772cf9b317f863 100644 --- a/src/core_plugins/console/api_server/spec/generated/count.json +++ b/src/core_plugins/console/api_server/spec/generated/count.json @@ -1,5 +1,5 @@ { - "_count": { + "count": { "url_params": { "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", @@ -31,6 +31,7 @@ "_count", "{indices}/_count", "{indices}/{type}/_count" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-count.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/create.json b/src/core_plugins/console/api_server/spec/generated/create.json index 7f0debab381883..484d641ebdfe91 100644 --- a/src/core_plugins/console/api_server/spec/generated/create.json +++ b/src/core_plugins/console/api_server/spec/generated/create.json @@ -1,5 +1,5 @@ { - "{index}/{type}/{id}/_create": { + "create": { "url_params": { "wait_for_active_shards": "", "parent": "", @@ -10,8 +10,6 @@ ], "routing": "", "timeout": "", - "timestamp": "", - "ttl": "", "version": "", "version_type": [ "internal", @@ -27,6 +25,7 @@ ], "patterns": [ "{indices}/{type}/{id}/_create" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-index_.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/delete.json b/src/core_plugins/console/api_server/spec/generated/delete.json index dbd16eabc995d7..b7cef230c97569 100644 --- a/src/core_plugins/console/api_server/spec/generated/delete.json +++ b/src/core_plugins/console/api_server/spec/generated/delete.json @@ -1,6 +1,7 @@ { - "{index}/{type}/{id}": { + "delete": { "url_params": { + "include_type_name": "", "wait_for_active_shards": "", "parent": "", "refresh": [ @@ -22,7 +23,9 @@ "DELETE" ], "patterns": [ - "{indices}/{type}/{id}" - ] + "{indices}/{type}/{id}", + "{indices}/_doc/{id}" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-delete.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/delete_by_query.json b/src/core_plugins/console/api_server/spec/generated/delete_by_query.json index 5c5ec5bae1bcc2..5339ff3e1f43e6 100644 --- a/src/core_plugins/console/api_server/spec/generated/delete_by_query.json +++ b/src/core_plugins/console/api_server/spec/generated/delete_by_query.json @@ -1,5 +1,5 @@ { - "{index}/_delete_by_query": { + "delete_by_query": { "url_params": { "analyzer": "", "analyze_wildcard": "__flag__", @@ -54,6 +54,7 @@ "patterns": [ "{indices}/_delete_by_query", "{indices}/{type}/_delete_by_query" - ] + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-delete-by-query.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/delete_script.json b/src/core_plugins/console/api_server/spec/generated/delete_script.json index d71fd4f0aef516..e99354c7379602 100644 --- a/src/core_plugins/console/api_server/spec/generated/delete_script.json +++ b/src/core_plugins/console/api_server/spec/generated/delete_script.json @@ -1,5 +1,5 @@ { - "_scripts/{id}": { + "delete_script": { "url_params": { "timeout": "", "master_timeout": "" @@ -9,6 +9,7 @@ ], "patterns": [ "_scripts/{id}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/exists.json b/src/core_plugins/console/api_server/spec/generated/exists.json index 1c8d9e7131a0b9..4a5a1f6a1bdd5c 100644 --- a/src/core_plugins/console/api_server/spec/generated/exists.json +++ b/src/core_plugins/console/api_server/spec/generated/exists.json @@ -1,5 +1,5 @@ { - "{index}/{type}/{id}": { + "exists": { "url_params": { "stored_fields": [], "parent": "", @@ -23,6 +23,7 @@ ], "patterns": [ "{indices}/{type}/{id}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/exists_source.json b/src/core_plugins/console/api_server/spec/generated/exists_source.json index b2b3df85a1cb1f..9eb4aceaeae015 100644 --- a/src/core_plugins/console/api_server/spec/generated/exists_source.json +++ b/src/core_plugins/console/api_server/spec/generated/exists_source.json @@ -1,5 +1,5 @@ { - "{index}/{type}/{id}/_source": { + "exists_source": { "url_params": { "parent": "", "preference": "random", @@ -22,6 +22,7 @@ ], "patterns": [ "{indices}/{type}/{id}/_source" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/explain.json b/src/core_plugins/console/api_server/spec/generated/explain.json index 5cda6504870e8e..5112e9f50c7d58 100644 --- a/src/core_plugins/console/api_server/spec/generated/explain.json +++ b/src/core_plugins/console/api_server/spec/generated/explain.json @@ -1,5 +1,5 @@ { - "{index}/{type}/{id}/_explain": { + "explain": { "url_params": { "analyze_wildcard": "__flag__", "analyzer": "", @@ -24,6 +24,7 @@ ], "patterns": [ "{indices}/{type}/{id}/_explain" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-explain.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/field_caps.json b/src/core_plugins/console/api_server/spec/generated/field_caps.json index 028cfb51fa5fd9..813734c4b94805 100644 --- a/src/core_plugins/console/api_server/spec/generated/field_caps.json +++ b/src/core_plugins/console/api_server/spec/generated/field_caps.json @@ -1,5 +1,5 @@ { - "_field_caps": { + "field_caps": { "url_params": { "fields": [], "ignore_unavailable": "__flag__", @@ -18,6 +18,7 @@ "patterns": [ "_field_caps", "{indices}/_field_caps" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-field-caps.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/get.json b/src/core_plugins/console/api_server/spec/generated/get.json index 170d6e35c6b5b6..f94caaad7cad17 100644 --- a/src/core_plugins/console/api_server/spec/generated/get.json +++ b/src/core_plugins/console/api_server/spec/generated/get.json @@ -1,6 +1,7 @@ { - "{index}/{type}/{id}": { + "get": { "url_params": { + "include_type_name": "", "stored_fields": [], "parent": "", "preference": "random", @@ -22,7 +23,9 @@ "GET" ], "patterns": [ - "{indices}/{type}/{id}" - ] + "{indices}/{type}/{id}", + "{indices}/_doc/{id}" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/get_script.json b/src/core_plugins/console/api_server/spec/generated/get_script.json index d4d217818ffc34..84c7eacb333785 100644 --- a/src/core_plugins/console/api_server/spec/generated/get_script.json +++ b/src/core_plugins/console/api_server/spec/generated/get_script.json @@ -1,11 +1,11 @@ { - "_scripts/{id}": { - "url_params": {}, + "get_script": { "methods": [ "GET" ], "patterns": [ "_scripts/{id}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/get_source.json b/src/core_plugins/console/api_server/spec/generated/get_source.json index 1820e47ec02354..da160be766c755 100644 --- a/src/core_plugins/console/api_server/spec/generated/get_source.json +++ b/src/core_plugins/console/api_server/spec/generated/get_source.json @@ -1,5 +1,5 @@ { - "{index}/{type}/{id}/_source": { + "get_source": { "url_params": { "parent": "", "preference": "random", @@ -22,6 +22,7 @@ ], "patterns": [ "{indices}/{type}/{id}/_source" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/index.json b/src/core_plugins/console/api_server/spec/generated/index.json index bd1a19c1fce264..7c837badafc8f2 100644 --- a/src/core_plugins/console/api_server/spec/generated/index.json +++ b/src/core_plugins/console/api_server/spec/generated/index.json @@ -1,6 +1,7 @@ { - "{index}/{type}": { + "index": { "url_params": { + "include_type_name": "", "wait_for_active_shards": "", "op_type": [ "index", @@ -14,8 +15,6 @@ ], "routing": "", "timeout": "", - "timestamp": "", - "ttl": "", "version": "", "version_type": [ "internal", @@ -31,7 +30,10 @@ ], "patterns": [ "{indices}/{type}", - "{indices}/{type}/{id}" - ] + "{indices}/{type}/{id}", + "{indices}/_doc/{id}", + "{indices}/_doc" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-index_.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.analyze.json b/src/core_plugins/console/api_server/spec/generated/indices.analyze.json index e8f59dcde08aca..b6f47c9caa7f5c 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.analyze.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.analyze.json @@ -1,5 +1,5 @@ { - "_analyze": { + "indices.analyze": { "url_params": { "index": "", "prefer_local": "__flag__", @@ -15,6 +15,7 @@ "patterns": [ "_analyze", "{indices}/_analyze" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-analyze.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.clear_cache.json b/src/core_plugins/console/api_server/spec/generated/indices.clear_cache.json index 300b22c8b767f8..83008ad8e4bbe3 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.clear_cache.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.clear_cache.json @@ -1,7 +1,6 @@ { - "_cache/clear": { + "indices.clear_cache": { "url_params": { - "field_data": "__flag__", "fielddata": "__flag__", "fields": [], "query": "__flag__", @@ -14,8 +13,6 @@ "all" ], "index": [], - "recycler": "__flag__", - "request_cache": "__flag__", "request": "__flag__" }, "methods": [ @@ -25,6 +22,7 @@ "patterns": [ "_cache/clear", "{indices}/_cache/clear" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-clearcache.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.close.json b/src/core_plugins/console/api_server/spec/generated/indices.close.json index 3948e51db89419..f1432dc44b5b56 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.close.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.close.json @@ -1,5 +1,5 @@ { - "{index}/_close": { + "indices.close": { "url_params": { "timeout": "", "master_timeout": "", @@ -17,6 +17,7 @@ ], "patterns": [ "{indices}/_close" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-open-close.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.create.json b/src/core_plugins/console/api_server/spec/generated/indices.create.json index 227c31ab7bfd64..4f53c65d40cb08 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.create.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.create.json @@ -1,16 +1,17 @@ { - "{index}": { + "indices.create": { "url_params": { + "include_type_name": "", "wait_for_active_shards": "", "timeout": "", - "master_timeout": "", - "update_all_types": "__flag__" + "master_timeout": "" }, "methods": [ "PUT" ], "patterns": [ "{indices}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-create-index.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.delete.json b/src/core_plugins/console/api_server/spec/generated/indices.delete.json index 37804b4bb32c5f..234c8c1e28de89 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.delete.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.delete.json @@ -1,5 +1,5 @@ { - "{index}": { + "indices.delete": { "url_params": { "timeout": "", "master_timeout": "", @@ -17,6 +17,7 @@ ], "patterns": [ "{indices}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-delete-index.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.delete_alias.json b/src/core_plugins/console/api_server/spec/generated/indices.delete_alias.json index 4782f00118f3ae..e055dcd9ab78ae 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.delete_alias.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.delete_alias.json @@ -1,5 +1,5 @@ { - "{index}/_alias/{name}": { + "indices.delete_alias": { "url_params": { "timeout": "", "master_timeout": "" @@ -10,6 +10,7 @@ "patterns": [ "{indices}/_alias/{name}", "{indices}/_aliases/{name}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.delete_template.json b/src/core_plugins/console/api_server/spec/generated/indices.delete_template.json index eb2f4e30b943a0..d215c42b06bd7a 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.delete_template.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.delete_template.json @@ -1,5 +1,5 @@ { - "_template/{name}": { + "indices.delete_template": { "url_params": { "timeout": "", "master_timeout": "" @@ -9,6 +9,7 @@ ], "patterns": [ "_template/{name}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.exists.json b/src/core_plugins/console/api_server/spec/generated/indices.exists.json index ab73e2be9f71f7..6a51a8784fa9fe 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.exists.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.exists.json @@ -1,5 +1,5 @@ { - "{index}": { + "indices.exists": { "url_params": { "local": "__flag__", "ignore_unavailable": "__flag__", @@ -18,6 +18,7 @@ ], "patterns": [ "{indices}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-exists.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.exists_alias.json b/src/core_plugins/console/api_server/spec/generated/indices.exists_alias.json index c708153bbd896c..e990998efef2e0 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.exists_alias.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.exists_alias.json @@ -1,5 +1,5 @@ { - "_alias/{name}": { + "indices.exists_alias": { "url_params": { "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", @@ -17,6 +17,7 @@ "patterns": [ "_alias/{name}", "{indices}/_alias/{name}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.exists_template.json b/src/core_plugins/console/api_server/spec/generated/indices.exists_template.json index 0c3889ea717c18..7c74deaa74bdd5 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.exists_template.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.exists_template.json @@ -1,5 +1,5 @@ { - "_template/{name}": { + "indices.exists_template": { "url_params": { "flat_settings": "__flag__", "master_timeout": "", @@ -10,6 +10,7 @@ ], "patterns": [ "_template/{name}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.exists_type.json b/src/core_plugins/console/api_server/spec/generated/indices.exists_type.json index 2072e297169b8d..d20e08ab2cf530 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.exists_type.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.exists_type.json @@ -1,5 +1,5 @@ { - "{index}/_mapping/{type}": { + "indices.exists_type": { "url_params": { "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", @@ -16,6 +16,7 @@ ], "patterns": [ "{indices}/_mapping/{type}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-types-exists.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.flush.json b/src/core_plugins/console/api_server/spec/generated/indices.flush.json index d49de7a9e02d67..2e2361edb21127 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.flush.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.flush.json @@ -1,5 +1,5 @@ { - "_flush": { + "indices.flush": { "url_params": { "force": "__flag__", "wait_if_ongoing": "__flag__", @@ -19,6 +19,7 @@ "patterns": [ "_flush", "{indices}/_flush" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-flush.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.flush_synced.json b/src/core_plugins/console/api_server/spec/generated/indices.flush_synced.json index a8a83568039a60..12e08963ebef51 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.flush_synced.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.flush_synced.json @@ -1,5 +1,5 @@ { - "_flush/synced": { + "indices.flush_synced": { "url_params": { "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", @@ -17,6 +17,7 @@ "patterns": [ "_flush/synced", "{indices}/_flush/synced" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-synced-flush.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.forcemerge.json b/src/core_plugins/console/api_server/spec/generated/indices.forcemerge.json index 36a81561b46f08..7b4e15a702afcd 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.forcemerge.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.forcemerge.json @@ -1,5 +1,5 @@ { - "_forcemerge": { + "indices.forcemerge": { "url_params": { "flush": "__flag__", "ignore_unavailable": "__flag__", @@ -11,8 +11,7 @@ "all" ], "max_num_segments": "dynamic", - "only_expunge_deletes": "__flag__", - "wait_for_merge": "__flag__" + "only_expunge_deletes": "__flag__" }, "methods": [ "POST" @@ -20,6 +19,7 @@ "patterns": [ "_forcemerge", "{indices}/_forcemerge" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-forcemerge.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.get.json b/src/core_plugins/console/api_server/spec/generated/indices.get.json index 38aa1a456417b9..d1bbac465adb27 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.get.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.get.json @@ -1,5 +1,5 @@ { - "{index}": { + "indices.get": { "url_params": { "local": "__flag__", "ignore_unavailable": "__flag__", @@ -18,6 +18,7 @@ ], "patterns": [ "{indices}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-index.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.get_alias.json b/src/core_plugins/console/api_server/spec/generated/indices.get_alias.json index bf87dbe45dcbbb..1b24c35f76d987 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.get_alias.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.get_alias.json @@ -1,5 +1,5 @@ { - "_alias/": { + "indices.get_alias": { "url_params": { "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", @@ -19,6 +19,7 @@ "_alias/{name}", "{indices}/_alias/{name}", "{indices}/_alias" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.get_field_mapping.json b/src/core_plugins/console/api_server/spec/generated/indices.get_field_mapping.json index fa80ec4884f2f3..66b72b592bee19 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.get_field_mapping.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.get_field_mapping.json @@ -1,5 +1,5 @@ { - "_mapping/field/{fields}": { + "indices.get_field_mapping": { "url_params": { "include_defaults": "__flag__", "ignore_unavailable": "__flag__", @@ -20,6 +20,7 @@ "{indices}/_mapping/field/{fields}", "_mapping/{type}/field/{fields}", "{indices}/_mapping/{type}/field/{fields}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-field-mapping.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.get_mapping.json b/src/core_plugins/console/api_server/spec/generated/indices.get_mapping.json index 9c52ab9084a846..832f16af2dd11e 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.get_mapping.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.get_mapping.json @@ -1,6 +1,7 @@ { - "_mapping": { + "indices.get_mapping": { "url_params": { + "include_type_name": "", "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", "expand_wildcards": [ @@ -19,6 +20,7 @@ "{indices}/_mapping", "_mapping/{type}", "{indices}/_mapping/{type}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-mapping.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.get_settings.json b/src/core_plugins/console/api_server/spec/generated/indices.get_settings.json index af1323524848d2..98bf919fd3511a 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.get_settings.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.get_settings.json @@ -1,5 +1,5 @@ { - "_settings": { + "indices.get_settings": { "url_params": { "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", @@ -21,6 +21,7 @@ "{indices}/_settings", "{indices}/_settings/{name}", "_settings/{name}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-get-settings.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.get_template.json b/src/core_plugins/console/api_server/spec/generated/indices.get_template.json index 6777313245d955..5949c1bcbe19d4 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.get_template.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.get_template.json @@ -1,5 +1,5 @@ { - "_template/{name}": { + "indices.get_template": { "url_params": { "flat_settings": "__flag__", "master_timeout": "", @@ -11,6 +11,7 @@ "patterns": [ "_template", "_template/{name}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.get_upgrade.json b/src/core_plugins/console/api_server/spec/generated/indices.get_upgrade.json index ce5f31b1b26014..7da594a5bf784b 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.get_upgrade.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.get_upgrade.json @@ -1,5 +1,5 @@ { - "_upgrade": { + "indices.get_upgrade": { "url_params": { "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", @@ -16,6 +16,7 @@ "patterns": [ "_upgrade", "{indices}/_upgrade" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-upgrade.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.open.json b/src/core_plugins/console/api_server/spec/generated/indices.open.json index b38ea29525a0d2..2b721566101fd2 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.open.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.open.json @@ -1,5 +1,5 @@ { - "{index}/_open": { + "indices.open": { "url_params": { "timeout": "", "master_timeout": "", @@ -18,6 +18,7 @@ ], "patterns": [ "{indices}/_open" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-open-close.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.put_alias.json b/src/core_plugins/console/api_server/spec/generated/indices.put_alias.json index db92dcf209c6a9..51151bd1238b31 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.put_alias.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.put_alias.json @@ -1,5 +1,5 @@ { - "{index}/_alias/{name}": { + "indices.put_alias": { "url_params": { "timeout": "", "master_timeout": "" @@ -11,6 +11,7 @@ "patterns": [ "{indices}/_alias/{name}", "{indices}/_aliases/{name}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.put_mapping.json b/src/core_plugins/console/api_server/spec/generated/indices.put_mapping.json new file mode 100644 index 00000000000000..53dcfdc715f1df --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/indices.put_mapping.json @@ -0,0 +1,32 @@ +{ + "put_mapping": { + "url_params": { + "include_type_name": "", + "timeout": "", + "master_timeout": "", + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ] + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "{indices}/{type}/_mapping", + "{indices}/_mapping/{type}", + "_mapping/{type}", + "{indices}/{type}/_mappings", + "{indices}/_mappings/{type}", + "_mappings/{type}", + "{indices}/_mappings", + "{indices}/_mapping" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-put-mapping.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/indices.put_settings.json b/src/core_plugins/console/api_server/spec/generated/indices.put_settings.json index 71bf53cc1e48ec..f4a0402721b041 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.put_settings.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.put_settings.json @@ -1,7 +1,8 @@ { - "_settings": { + "put_settings": { "url_params": { "master_timeout": "", + "timeout": "", "preserve_existing": "__flag__", "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", @@ -19,6 +20,7 @@ "patterns": [ "_settings", "{indices}/_settings" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-update-settings.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.put_template.json b/src/core_plugins/console/api_server/spec/generated/indices.put_template.json index f85e28ca9eb9bb..b27069a99bef6a 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.put_template.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.put_template.json @@ -1,5 +1,5 @@ { - "_template/{name}": { + "indices.put_template": { "url_params": { "order": "", "create": "__flag__", @@ -13,6 +13,7 @@ ], "patterns": [ "_template/{name}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.recovery.json b/src/core_plugins/console/api_server/spec/generated/indices.recovery.json index cf6f7bd78dcdca..2e869f065002b4 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.recovery.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.recovery.json @@ -1,5 +1,5 @@ { - "_recovery": { + "indices.recovery": { "url_params": { "detailed": "__flag__", "active_only": "__flag__" @@ -10,6 +10,7 @@ "patterns": [ "_recovery", "{indices}/_recovery" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-recovery.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.refresh.json b/src/core_plugins/console/api_server/spec/generated/indices.refresh.json index 17ee45909a11be..a696d7b1f4180b 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.refresh.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.refresh.json @@ -1,5 +1,5 @@ { - "_refresh": { + "indices.refresh": { "url_params": { "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", @@ -17,6 +17,7 @@ "patterns": [ "_refresh", "{indices}/_refresh" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-refresh.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.rollover.json b/src/core_plugins/console/api_server/spec/generated/indices.rollover.json index b6abbdc0a8ffb1..8fe6fabdf67323 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.rollover.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.rollover.json @@ -1,5 +1,5 @@ { - "{alias}/_rollover": { + "indices.rollover": { "url_params": { "timeout": "", "dry_run": "__flag__", @@ -12,6 +12,7 @@ "patterns": [ "{alias}/_rollover", "{alias}/_rollover/{new_index}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-rollover-index.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.segments.json b/src/core_plugins/console/api_server/spec/generated/indices.segments.json index 6e613f46667788..b3f87eab2251ba 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.segments.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.segments.json @@ -1,5 +1,5 @@ { - "_segments": { + "indices.segments": { "url_params": { "ignore_unavailable": "__flag__", "allow_no_indices": "__flag__", @@ -17,6 +17,7 @@ "patterns": [ "_segments", "{indices}/_segments" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-segments.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.shard_stores.json b/src/core_plugins/console/api_server/spec/generated/indices.shard_stores.json index 2972513ae6c28e..7822604d1b5f44 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.shard_stores.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.shard_stores.json @@ -1,5 +1,5 @@ { - "_shard_stores": { + "indices.shard_stores": { "url_params": { "status": [], "ignore_unavailable": "__flag__", @@ -17,6 +17,7 @@ "patterns": [ "_shard_stores", "{indices}/_shard_stores" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-shards-stores.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.shrink.json b/src/core_plugins/console/api_server/spec/generated/indices.shrink.json index 70e7a11ebafa59..60978da9e5663c 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.shrink.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.shrink.json @@ -1,5 +1,5 @@ { - "{index}/_shrink/{target}": { + "indices.shrink": { "url_params": { "timeout": "", "master_timeout": "", @@ -11,6 +11,7 @@ ], "patterns": [ "{indices}/_shrink/{target}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-shrink-index.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.split.json b/src/core_plugins/console/api_server/spec/generated/indices.split.json index 78b55395e2c603..265ed882a2f4b2 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.split.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.split.json @@ -1,5 +1,5 @@ { - "{index}/_split/{target}": { + "indices.split": { "url_params": { "timeout": "", "master_timeout": "", @@ -11,6 +11,7 @@ ], "patterns": [ "{indices}/_split/{target}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-split-index.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.stats.json b/src/core_plugins/console/api_server/spec/generated/indices.stats.json index 4f2ba3482f1043..74c7cd2821f53c 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.stats.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.stats.json @@ -1,5 +1,5 @@ { - "_stats": { + "indices.stats": { "url_params": { "completion_fields": [], "fielddata_fields": [], @@ -42,6 +42,7 @@ "suggest", "warmer" ] - } + }, + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-stats.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.update_aliases.json b/src/core_plugins/console/api_server/spec/generated/indices.update_aliases.json index b9923e3e014383..066efa7b1c4fd9 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.update_aliases.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.update_aliases.json @@ -1,5 +1,5 @@ { - "_aliases": { + "indices.update_aliases": { "url_params": { "timeout": "", "master_timeout": "" @@ -9,6 +9,7 @@ ], "patterns": [ "_aliases" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-aliases.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.upgrade.json b/src/core_plugins/console/api_server/spec/generated/indices.upgrade.json index 2ce2d09f4e89d8..3382f069a00ec4 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.upgrade.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.upgrade.json @@ -1,5 +1,5 @@ { - "_upgrade": { + "indices.upgrade": { "url_params": { "allow_no_indices": "__flag__", "expand_wildcards": [ @@ -18,6 +18,7 @@ "patterns": [ "_upgrade", "{indices}/_upgrade" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/indices-upgrade.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/indices.validate_query.json b/src/core_plugins/console/api_server/spec/generated/indices.validate_query.json index cd74add40d30db..abfaacfd54f256 100644 --- a/src/core_plugins/console/api_server/spec/generated/indices.validate_query.json +++ b/src/core_plugins/console/api_server/spec/generated/indices.validate_query.json @@ -1,5 +1,5 @@ { - "_validate/query": { + "indices.validate_query": { "url_params": { "explain": "__flag__", "ignore_unavailable": "__flag__", @@ -30,6 +30,7 @@ "_validate/query", "{indices}/_validate/query", "{indices}/{type}/_validate/query" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-validate.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/info.json b/src/core_plugins/console/api_server/spec/generated/info.json new file mode 100644 index 00000000000000..4a70e6124afec5 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/info.json @@ -0,0 +1,11 @@ +{ + "info": { + "methods": [ + "GET" + ], + "patterns": [ + "" + ], + "documentation": "http://www.elastic.co/guide/" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/ingest.delete_pipeline.json b/src/core_plugins/console/api_server/spec/generated/ingest.delete_pipeline.json new file mode 100644 index 00000000000000..a1c628e1e51167 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/ingest.delete_pipeline.json @@ -0,0 +1,15 @@ +{ + "ingest.delete_pipeline": { + "url_params": { + "master_timeout": "", + "timeout": "" + }, + "methods": [ + "DELETE" + ], + "patterns": [ + "_ingest/pipeline/{id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/plugins/master/ingest.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/ingest.get_pipeline.json b/src/core_plugins/console/api_server/spec/generated/ingest.get_pipeline.json new file mode 100644 index 00000000000000..cf3fb455d2ed3c --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/ingest.get_pipeline.json @@ -0,0 +1,15 @@ +{ + "ingest.get_pipeline": { + "url_params": { + "master_timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_ingest/pipeline", + "_ingest/pipeline/{id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/plugins/master/ingest.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/ingest.processor_grok.json b/src/core_plugins/console/api_server/spec/generated/ingest.processor_grok.json new file mode 100644 index 00000000000000..42c593a1b88b45 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/ingest.processor_grok.json @@ -0,0 +1,11 @@ +{ + "ingest.processor_grok": { + "methods": [ + "GET" + ], + "patterns": [ + "_ingest/processor/grok" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/plugins/master/ingest.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/ingest.put_pipeline.json b/src/core_plugins/console/api_server/spec/generated/ingest.put_pipeline.json new file mode 100644 index 00000000000000..0e7f7cab9ad6a6 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/ingest.put_pipeline.json @@ -0,0 +1,15 @@ +{ + "ingest.put_pipeline": { + "url_params": { + "master_timeout": "", + "timeout": "" + }, + "methods": [ + "PUT" + ], + "patterns": [ + "_ingest/pipeline/{id}" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/plugins/master/ingest.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/ingest.simulate.json b/src/core_plugins/console/api_server/spec/generated/ingest.simulate.json new file mode 100644 index 00000000000000..2bb84486c46963 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/ingest.simulate.json @@ -0,0 +1,16 @@ +{ + "ingest.simulate": { + "url_params": { + "verbose": "__flag__" + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_ingest/pipeline/_simulate", + "_ingest/pipeline/{id}/_simulate" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/plugins/master/ingest.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/mget.json b/src/core_plugins/console/api_server/spec/generated/mget.json new file mode 100644 index 00000000000000..67cd67899568b7 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/mget.json @@ -0,0 +1,24 @@ +{ + "mget": { + "url_params": { + "stored_fields": [], + "preference": "random", + "realtime": "__flag__", + "refresh": "__flag__", + "routing": "", + "_source": [], + "_source_exclude": [], + "_source_include": [] + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_mget", + "{indices}/_mget", + "{indices}/{type}/_mget" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-multi-get.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/msearch.json b/src/core_plugins/console/api_server/spec/generated/msearch.json new file mode 100644 index 00000000000000..a79edc5f461704 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/msearch.json @@ -0,0 +1,25 @@ +{ + "msearch": { + "url_params": { + "search_type": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch" + ], + "max_concurrent_searches": "", + "typed_keys": "__flag__", + "pre_filter_shard_size": "" + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_msearch", + "{indices}/_msearch", + "{indices}/{type}/_msearch" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-multi-search.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/msearch_template.json b/src/core_plugins/console/api_server/spec/generated/msearch_template.json new file mode 100644 index 00000000000000..56b1b418eaddac --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/msearch_template.json @@ -0,0 +1,24 @@ +{ + "msearch_template": { + "url_params": { + "search_type": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch" + ], + "typed_keys": "__flag__", + "max_concurrent_searches": "" + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_msearch/template", + "{indices}/_msearch/template", + "{indices}/{type}/_msearch/template" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/mtermvectors.json b/src/core_plugins/console/api_server/spec/generated/mtermvectors.json new file mode 100644 index 00000000000000..9f057d9ac76b78 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/mtermvectors.json @@ -0,0 +1,34 @@ +{ + "mtermvectors": { + "url_params": { + "ids": [], + "term_statistics": "__flag__", + "field_statistics": "__flag__", + "fields": [], + "offsets": "__flag__", + "positions": "__flag__", + "payloads": "__flag__", + "preference": "random", + "routing": "", + "parent": "", + "realtime": "__flag__", + "version": "", + "version_type": [ + "internal", + "external", + "external_gte", + "force" + ] + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_mtermvectors", + "{indices}/_mtermvectors", + "{indices}/{type}/_mtermvectors" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-multi-termvectors.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/nodes.hot_threads.json b/src/core_plugins/console/api_server/spec/generated/nodes.hot_threads.json new file mode 100644 index 00000000000000..a17c33e22d15ba --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/nodes.hot_threads.json @@ -0,0 +1,30 @@ +{ + "nodes.hot_threads": { + "url_params": { + "interval": "", + "snapshots": "10", + "threads": "3", + "ignore_idle_threads": "__flag__", + "type": [ + "cpu", + "wait", + "block" + ], + "timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_cluster/nodes/hotthreads", + "_cluster/nodes/hot_threads", + "_cluster/nodes/{nodes}/hotthreads", + "_cluster/nodes/{nodes}/hot_threads", + "_nodes/hotthreads", + "_nodes/hot_threads", + "_nodes/{nodes}/hotthreads", + "_nodes/{nodes}/hot_threads" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-hot-threads.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/nodes.info.json b/src/core_plugins/console/api_server/spec/generated/nodes.info.json new file mode 100644 index 00000000000000..a4938acb27538f --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/nodes.info.json @@ -0,0 +1,32 @@ +{ + "nodes.info": { + "url_params": { + "flat_settings": "__flag__", + "timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_nodes", + "_nodes/{nodes}", + "_nodes/{metrics}", + "_nodes/{nodes}/{metrics}" + ], + "url_components": { + "nodes": null, + "metrics": [ + "http", + "ingest", + "jvm", + "os", + "plugins", + "process", + "settings", + "thread_pool", + "transport" + ] + }, + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-info.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/nodes.stats.json b/src/core_plugins/console/api_server/spec/generated/nodes.stats.json new file mode 100644 index 00000000000000..0073f224e3abf3 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/nodes.stats.json @@ -0,0 +1,64 @@ +{ + "nodes.stats": { + "url_params": { + "completion_fields": [], + "fielddata_fields": [], + "fields": [], + "groups": "__flag__", + "level": [ + "indices", + "node", + "shards" + ], + "types": [], + "timeout": "", + "include_segment_file_sizes": "__flag__" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_nodes/stats", + "_nodes/{nodes}/stats", + "_nodes/stats/{metrics}", + "_nodes/{nodes}/stats/{metrics}", + "_nodes/stats/{metrics}/{index_metric}", + "_nodes/{nodes}/stats/{metrics}/{index_metric}" + ], + "url_components": { + "metrics": [ + "_all", + "breaker", + "discovery", + "fs", + "http", + "indices", + "jvm", + "os", + "process", + "thread_pool", + "transport" + ], + "index_metric": [ + "_all", + "completion", + "docs", + "fielddata", + "flush", + "get", + "indexing", + "merge", + "query_cache", + "refresh", + "request_cache", + "search", + "segments", + "store", + "suggest", + "warmer" + ], + "nodes": null + }, + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-stats.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/nodes.usage.json b/src/core_plugins/console/api_server/spec/generated/nodes.usage.json new file mode 100644 index 00000000000000..ac280632721d77 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/nodes.usage.json @@ -0,0 +1,24 @@ +{ + "nodes.usage": { + "url_params": { + "timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_nodes/usage", + "_nodes/{nodes}/usage", + "_nodes/usage/{metrics}", + "_nodes/{nodes}/usage/{metrics}" + ], + "url_components": { + "metrics": [ + "_all", + "rest_actions" + ], + "nodes": null + }, + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-usage.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/ping.json b/src/core_plugins/console/api_server/spec/generated/ping.json new file mode 100644 index 00000000000000..88c83ece5882c1 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/ping.json @@ -0,0 +1,11 @@ +{ + "ping": { + "methods": [ + "HEAD" + ], + "patterns": [ + "" + ], + "documentation": "http://www.elastic.co/guide/" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/put_script.json b/src/core_plugins/console/api_server/spec/generated/put_script.json new file mode 100644 index 00000000000000..d386a2709c99f8 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/put_script.json @@ -0,0 +1,18 @@ +{ + "put_script": { + "url_params": { + "timeout": "", + "master_timeout": "", + "context": "" + }, + "methods": [ + "PUT", + "POST" + ], + "patterns": [ + "_scripts/{id}", + "_scripts/{id}/{context}" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/rank_eval.json b/src/core_plugins/console/api_server/spec/generated/rank_eval.json new file mode 100644 index 00000000000000..620f1c629d9592 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/rank_eval.json @@ -0,0 +1,23 @@ +{ + "rank_eval": { + "url_params": { + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ] + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_rank_eval", + "{indices}/_rank_eval" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-rank-eval.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/reindex.json b/src/core_plugins/console/api_server/spec/generated/reindex.json new file mode 100644 index 00000000000000..91b8bfaa406d89 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/reindex.json @@ -0,0 +1,19 @@ +{ + "reindex": { + "url_params": { + "refresh": "__flag__", + "timeout": "", + "wait_for_active_shards": "", + "wait_for_completion": "__flag__", + "requests_per_second": "", + "slices": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "_reindex" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-reindex.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/reindex_rethrottle.json b/src/core_plugins/console/api_server/spec/generated/reindex_rethrottle.json new file mode 100644 index 00000000000000..12c64b5bd5c0ff --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/reindex_rethrottle.json @@ -0,0 +1,16 @@ +{ + "reindex_rethrottle": { + "url_params": { + "requests_per_second": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "_reindex/{task_id}/_rethrottle", + "_update_by_query/{task_id}/_rethrottle", + "_delete_by_query/{task_id}/_rethrottle" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-reindex.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/render_search_template.json b/src/core_plugins/console/api_server/spec/generated/render_search_template.json new file mode 100644 index 00000000000000..b9ce5d8a506da0 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/render_search_template.json @@ -0,0 +1,13 @@ +{ + "render_search_template": { + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_render/template", + "_render/template/{id}" + ], + "documentation": "http://www.elasticsearch.org/guide/en/elasticsearch/reference/master/search-template.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/scripts_painless_execute.json b/src/core_plugins/console/api_server/spec/generated/scripts_painless_execute.json new file mode 100644 index 00000000000000..a565e43c71b34a --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/scripts_painless_execute.json @@ -0,0 +1,12 @@ +{ + "scripts_painless_execute": { + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_scripts/painless/_execute" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/painless/master/painless-execute-api.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/scroll.json b/src/core_plugins/console/api_server/spec/generated/scroll.json new file mode 100644 index 00000000000000..05ffc69793ee67 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/scroll.json @@ -0,0 +1,17 @@ +{ + "scroll": { + "url_params": { + "scroll": "", + "scroll_id": "" + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_search/scroll", + "_search/scroll/{scroll_id}" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-request-scroll.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/search.json b/src/core_plugins/console/api_server/spec/generated/search.json new file mode 100644 index 00000000000000..21851d8b621445 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/search.json @@ -0,0 +1,70 @@ +{ + "search": { + "url_params": { + "include_type_name": "", + "analyzer": "", + "analyze_wildcard": "__flag__", + "default_operator": [ + "AND", + "OR" + ], + "df": "", + "explain": "__flag__", + "stored_fields": [], + "docvalue_fields": [], + "from": "0", + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ], + "lenient": "__flag__", + "preference": "random", + "q": "", + "routing": [], + "scroll": "", + "search_type": [ + "query_then_fetch", + "dfs_query_then_fetch" + ], + "size": "10", + "sort": [], + "_source": [], + "_source_exclude": [], + "_source_include": [], + "terminate_after": "", + "stats": [], + "suggest_field": "", + "suggest_mode": [ + "missing", + "popular", + "always" + ], + "suggest_size": "", + "suggest_text": "", + "timeout": "", + "track_scores": "__flag__", + "track_total_hits": "__flag__", + "allow_partial_search_results": "__flag__", + "typed_keys": "__flag__", + "version": "__flag__", + "request_cache": "__flag__", + "batched_reduce_size": "", + "max_concurrent_shard_requests": "", + "pre_filter_shard_size": "" + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_search", + "{indices}/_search", + "{indices}/{type}/_search" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-search.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/search_shards.json b/src/core_plugins/console/api_server/spec/generated/search_shards.json new file mode 100644 index 00000000000000..af500f5994daea --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/search_shards.json @@ -0,0 +1,26 @@ +{ + "search_shards": { + "url_params": { + "preference": "random", + "routing": "", + "local": "__flag__", + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ] + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_search_shards", + "{indices}/_search_shards" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/search-shards.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/search_template.json b/src/core_plugins/console/api_server/spec/generated/search_template.json new file mode 100644 index 00000000000000..8058648459017f --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/search_template.json @@ -0,0 +1,36 @@ +{ + "search_template": { + "url_params": { + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ], + "preference": "random", + "routing": [], + "scroll": "", + "search_type": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch" + ], + "explain": "__flag__", + "profile": "__flag__", + "typed_keys": "__flag__" + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "_search/template", + "{indices}/_search/template", + "{indices}/{type}/_search/template" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/snapshot.create.json b/src/core_plugins/console/api_server/spec/generated/snapshot.create.json index 2569de2d9e0635..6670a1f2f39d9f 100644 --- a/src/core_plugins/console/api_server/spec/generated/snapshot.create.json +++ b/src/core_plugins/console/api_server/spec/generated/snapshot.create.json @@ -10,6 +10,7 @@ ], "patterns": [ "_snapshot/{repository}/{snapshot}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/snapshot.create_repository.json b/src/core_plugins/console/api_server/spec/generated/snapshot.create_repository.json index fe7025853ab2b6..180724c1495fc1 100644 --- a/src/core_plugins/console/api_server/spec/generated/snapshot.create_repository.json +++ b/src/core_plugins/console/api_server/spec/generated/snapshot.create_repository.json @@ -11,6 +11,7 @@ ], "patterns": [ "_snapshot/{repository}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/snapshot.delete.json b/src/core_plugins/console/api_server/spec/generated/snapshot.delete.json index da7e99a862eb5f..2600179997e770 100644 --- a/src/core_plugins/console/api_server/spec/generated/snapshot.delete.json +++ b/src/core_plugins/console/api_server/spec/generated/snapshot.delete.json @@ -8,6 +8,7 @@ ], "patterns": [ "_snapshot/{repository}/{snapshot}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/snapshot.delete_repository.json b/src/core_plugins/console/api_server/spec/generated/snapshot.delete_repository.json index 28ba2c6179d339..0b613b7677fa04 100644 --- a/src/core_plugins/console/api_server/spec/generated/snapshot.delete_repository.json +++ b/src/core_plugins/console/api_server/spec/generated/snapshot.delete_repository.json @@ -9,6 +9,7 @@ ], "patterns": [ "_snapshot/{repository}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/snapshot.get.json b/src/core_plugins/console/api_server/spec/generated/snapshot.get.json index 4107e6a3296c95..29975fd72d6518 100644 --- a/src/core_plugins/console/api_server/spec/generated/snapshot.get.json +++ b/src/core_plugins/console/api_server/spec/generated/snapshot.get.json @@ -10,6 +10,7 @@ ], "patterns": [ "_snapshot/{repository}/{snapshot}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/snapshot.get_repository.json b/src/core_plugins/console/api_server/spec/generated/snapshot.get_repository.json index 2c70976170bdb7..7d6e5b683c1c56 100644 --- a/src/core_plugins/console/api_server/spec/generated/snapshot.get_repository.json +++ b/src/core_plugins/console/api_server/spec/generated/snapshot.get_repository.json @@ -10,6 +10,7 @@ "patterns": [ "_snapshot", "_snapshot/{repository}" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/snapshot.restore.json b/src/core_plugins/console/api_server/spec/generated/snapshot.restore.json index 1b4c919ee77bb4..130d3f51594a93 100644 --- a/src/core_plugins/console/api_server/spec/generated/snapshot.restore.json +++ b/src/core_plugins/console/api_server/spec/generated/snapshot.restore.json @@ -9,6 +9,7 @@ ], "patterns": [ "_snapshot/{repository}/{snapshot}/_restore" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/snapshot.status.json b/src/core_plugins/console/api_server/spec/generated/snapshot.status.json index ed4ee15250898f..1e0ea8c1f6d7ef 100644 --- a/src/core_plugins/console/api_server/spec/generated/snapshot.status.json +++ b/src/core_plugins/console/api_server/spec/generated/snapshot.status.json @@ -11,6 +11,7 @@ "_snapshot/_status", "_snapshot/{repository}/_status", "_snapshot/{repository}/{snapshot}/_status" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/snapshot.verify_repository.json b/src/core_plugins/console/api_server/spec/generated/snapshot.verify_repository.json index 6a61d7321c56da..a1e8bef6163953 100644 --- a/src/core_plugins/console/api_server/spec/generated/snapshot.verify_repository.json +++ b/src/core_plugins/console/api_server/spec/generated/snapshot.verify_repository.json @@ -9,6 +9,7 @@ ], "patterns": [ "_snapshot/{repository}/_verify" - ] + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html" } } diff --git a/src/core_plugins/console/api_server/spec/generated/tasks.cancel.json b/src/core_plugins/console/api_server/spec/generated/tasks.cancel.json new file mode 100644 index 00000000000000..42a8daeae8e39e --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/tasks.cancel.json @@ -0,0 +1,17 @@ +{ + "tasks.cancel": { + "url_params": { + "nodes": [], + "actions": [], + "parent_task_id": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "_tasks/_cancel", + "_tasks/{task_id}/_cancel" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/tasks.get.json b/src/core_plugins/console/api_server/spec/generated/tasks.get.json new file mode 100644 index 00000000000000..92230d0ace495b --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/tasks.get.json @@ -0,0 +1,15 @@ +{ + "tasks.get": { + "url_params": { + "wait_for_completion": "__flag__", + "timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_tasks/{task_id}" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/tasks.list.json b/src/core_plugins/console/api_server/spec/generated/tasks.list.json new file mode 100644 index 00000000000000..bf9142d2367881 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/tasks.list.json @@ -0,0 +1,24 @@ +{ + "tasks.list": { + "url_params": { + "nodes": [], + "actions": [], + "detailed": "__flag__", + "parent_task_id": "", + "wait_for_completion": "__flag__", + "group_by": [ + "nodes", + "parents", + "none" + ], + "timeout": "" + }, + "methods": [ + "GET" + ], + "patterns": [ + "_tasks" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/termvectors.json b/src/core_plugins/console/api_server/spec/generated/termvectors.json new file mode 100644 index 00000000000000..624baa2a129576 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/termvectors.json @@ -0,0 +1,32 @@ +{ + "termvectors": { + "url_params": { + "term_statistics": "__flag__", + "field_statistics": "__flag__", + "fields": [], + "offsets": "__flag__", + "positions": "__flag__", + "payloads": "__flag__", + "preference": "random", + "routing": "", + "parent": "", + "realtime": "__flag__", + "version": "", + "version_type": [ + "internal", + "external", + "external_gte", + "force" + ] + }, + "methods": [ + "GET", + "POST" + ], + "patterns": [ + "{indices}/{type}/_termvectors", + "{indices}/{type}/{id}/_termvectors" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-termvectors.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/update.json b/src/core_plugins/console/api_server/spec/generated/update.json new file mode 100644 index 00000000000000..b3d6a134218121 --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/update.json @@ -0,0 +1,34 @@ +{ + "update": { + "url_params": { + "include_type_name": "", + "wait_for_active_shards": "", + "_source": [], + "_source_exclude": [], + "_source_include": [], + "lang": "painless", + "parent": "", + "refresh": [ + "true", + "false", + "wait_for" + ], + "retry_on_conflict": "0", + "routing": "", + "timeout": "", + "version": "", + "version_type": [ + "internal", + "force" + ] + }, + "methods": [ + "POST" + ], + "patterns": [ + "{indices}/{type}/{id}/_update", + "{indices}/_doc/{id}/_update" + ], + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-update.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/generated/update_by_query.json b/src/core_plugins/console/api_server/spec/generated/update_by_query.json new file mode 100644 index 00000000000000..8ae4427ff7339d --- /dev/null +++ b/src/core_plugins/console/api_server/spec/generated/update_by_query.json @@ -0,0 +1,62 @@ +{ + "update_by_query": { + "url_params": { + "analyzer": "", + "analyze_wildcard": "__flag__", + "default_operator": [ + "AND", + "OR" + ], + "df": "", + "from": "0", + "ignore_unavailable": "__flag__", + "allow_no_indices": "__flag__", + "conflicts": [ + "abort", + "proceed" + ], + "expand_wildcards": [ + "open", + "closed", + "none", + "all" + ], + "lenient": "__flag__", + "pipeline": "none", + "preference": "random", + "q": "", + "routing": [], + "scroll": "", + "search_type": [ + "query_then_fetch", + "dfs_query_then_fetch" + ], + "search_timeout": "", + "size": "10", + "sort": [], + "_source": [], + "_source_exclude": [], + "_source_include": [], + "terminate_after": "", + "stats": [], + "version": "__flag__", + "version_type": "__flag__", + "request_cache": "__flag__", + "refresh": "__flag__", + "timeout": "", + "wait_for_active_shards": "", + "scroll_size": "", + "wait_for_completion": "__flag__", + "requests_per_second": "", + "slices": "" + }, + "methods": [ + "POST" + ], + "patterns": [ + "{indices}/_update_by_query", + "{indices}/{type}/_update_by_query" + ], + "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-update-by-query.html" + } +} diff --git a/src/core_plugins/console/api_server/spec/index.js b/src/core_plugins/console/api_server/spec/index.js index f26d402d50a699..95fe8ce57ac03d 100644 --- a/src/core_plugins/console/api_server/spec/index.js +++ b/src/core_plugins/console/api_server/spec/index.js @@ -1,7 +1,26 @@ -const glob = require('glob'); -const { join, basename } = require('path'); -const { readFileSync } = require('fs'); -const { merge } = require('lodash'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import glob from 'glob'; +import { join, basename } from 'path'; +import { readFileSync } from 'fs'; +import { merge } from 'lodash'; const extensionSpecFilePaths = []; export function getSpec() { diff --git a/src/core_plugins/console/api_server/spec/overrides/cluster.health.json b/src/core_plugins/console/api_server/spec/overrides/cluster.health.json index d69041e51e2173..7e1655e680b8fb 100644 --- a/src/core_plugins/console/api_server/spec/overrides/cluster.health.json +++ b/src/core_plugins/console/api_server/spec/overrides/cluster.health.json @@ -1,5 +1,5 @@ { - "_cluster/health": { + "cluster.health": { "url_params": { "master_timeout": "30s", "timeout": "30s", diff --git a/src/core_plugins/console/api_server/spec/overrides/cluster.put_settings.json b/src/core_plugins/console/api_server/spec/overrides/cluster.put_settings.json index 3cfaca8c9a5ad2..bad5ae83070bdb 100644 --- a/src/core_plugins/console/api_server/spec/overrides/cluster.put_settings.json +++ b/src/core_plugins/console/api_server/spec/overrides/cluster.put_settings.json @@ -1,5 +1,5 @@ { - "_cluster/settings": { + "cluster.put_settings": { "data_autocomplete_rules": { "persistent": { "cluster": { diff --git a/src/core_plugins/console/api_server/spec/overrides/cluster.reroute.json b/src/core_plugins/console/api_server/spec/overrides/cluster.reroute.json index e87feef62427bb..27a403970c51f4 100644 --- a/src/core_plugins/console/api_server/spec/overrides/cluster.reroute.json +++ b/src/core_plugins/console/api_server/spec/overrides/cluster.reroute.json @@ -1,5 +1,5 @@ { - "_cluster/reroute": { + "cluster.reroute": { "data_autocomplete_rules": { "commands": [ { diff --git a/src/core_plugins/console/api_server/spec/overrides/count.json b/src/core_plugins/console/api_server/spec/overrides/count.json index 780cae861ea2c5..1591c1dbfa943c 100644 --- a/src/core_plugins/console/api_server/spec/overrides/count.json +++ b/src/core_plugins/console/api_server/spec/overrides/count.json @@ -1,5 +1,5 @@ { - "_count": { + "count": { "priority": 10, "data_autocomplete_rules": { "query": {} diff --git a/src/core_plugins/console/api_server/spec/overrides/create.json b/src/core_plugins/console/api_server/spec/overrides/create.json index 9ff10b5edf6ff5..0bbf456245c841 100644 --- a/src/core_plugins/console/api_server/spec/overrides/create.json +++ b/src/core_plugins/console/api_server/spec/overrides/create.json @@ -1,5 +1,5 @@ { - "{index}/{type}/{id}/_create": { + "create": { "url_params": { "timeout": "1m", "ttl": "5m", diff --git a/src/core_plugins/console/api_server/spec/overrides/indices.analyze.json b/src/core_plugins/console/api_server/spec/overrides/indices.analyze.json index d85e8ee0605b32..4ab4fc39304372 100644 --- a/src/core_plugins/console/api_server/spec/overrides/indices.analyze.json +++ b/src/core_plugins/console/api_server/spec/overrides/indices.analyze.json @@ -1,5 +1,5 @@ { - "_analyze": { + "indices.analyze": { "data_autocomplete_rules": { "text": [], "field": "{field}", diff --git a/src/core_plugins/console/api_server/spec/overrides/indices.create.json b/src/core_plugins/console/api_server/spec/overrides/indices.create.json index a06336cdf18a27..60c2025314a573 100644 --- a/src/core_plugins/console/api_server/spec/overrides/indices.create.json +++ b/src/core_plugins/console/api_server/spec/overrides/indices.create.json @@ -1,14 +1,11 @@ { - "{index}": { - "patterns": [ - "{index}" - ], + "indices.create": { "data_autocomplete_rules": { "mappings": { - "__scope_link": "_put_mapping" + "__scope_link": "put_mapping" }, "settings": { - "__scope_link": "_settings_autocomplete" + "__scope_link": "put_settings" }, "aliases": { "__template": { diff --git a/src/core_plugins/console/api_server/spec/overrides/indices.get_field_mapping.json b/src/core_plugins/console/api_server/spec/overrides/indices.get_field_mapping.json index 0c846df2dff7d8..ef06ad6b01726c 100644 --- a/src/core_plugins/console/api_server/spec/overrides/indices.get_field_mapping.json +++ b/src/core_plugins/console/api_server/spec/overrides/indices.get_field_mapping.json @@ -1,5 +1,5 @@ { - "_mapping/field/{fields}": { + "indices.get_field_mapping": { "priority": 10 } } diff --git a/src/core_plugins/console/api_server/spec/overrides/indices.get_mapping.json b/src/core_plugins/console/api_server/spec/overrides/indices.get_mapping.json index c962c03ab6e4f6..bc9f208ae63dbd 100644 --- a/src/core_plugins/console/api_server/spec/overrides/indices.get_mapping.json +++ b/src/core_plugins/console/api_server/spec/overrides/indices.get_mapping.json @@ -1,5 +1,5 @@ { - "_mapping": { + "indices.get_mapping": { "priority": 10 } } diff --git a/src/core_plugins/console/api_server/spec/overrides/indices.put_alias.json b/src/core_plugins/console/api_server/spec/overrides/indices.put_alias.json index 3181c84c697452..2669f5e5e4fff1 100644 --- a/src/core_plugins/console/api_server/spec/overrides/indices.put_alias.json +++ b/src/core_plugins/console/api_server/spec/overrides/indices.put_alias.json @@ -1,5 +1,5 @@ { - "{index}/_alias/{name}": { + "indices.put_alias": { "data_autocomplete_rules": { "filter": {}, "routing": "1", diff --git a/src/core_plugins/console/api_server/spec/overrides/indices.put_settings.json b/src/core_plugins/console/api_server/spec/overrides/indices.put_settings.json index ff86d6c095babc..ba13502896763d 100644 --- a/src/core_plugins/console/api_server/spec/overrides/indices.put_settings.json +++ b/src/core_plugins/console/api_server/spec/overrides/indices.put_settings.json @@ -1,5 +1,5 @@ { - "_settings_autocomplete": { + "put_settings": { "data_autocomplete_rules": { "refresh_interval": "1s", "number_of_shards": 5, diff --git a/src/core_plugins/console/api_server/spec/overrides/indices.put_template.json b/src/core_plugins/console/api_server/spec/overrides/indices.put_template.json index 57528a2c79c89e..ed8a519021adc5 100644 --- a/src/core_plugins/console/api_server/spec/overrides/indices.put_template.json +++ b/src/core_plugins/console/api_server/spec/overrides/indices.put_template.json @@ -1,10 +1,10 @@ { - "_template/{name}": { + "indices.put_template": { "data_autocomplete_rules": { "template": "index*", "warmers": { "__scope_link": "_warmer" }, - "mappings": { "__scope_link": "_mapping" }, - "settings": { "__scope_link": "_settings_autocomplete" } + "mappings": { "__scope_link": "put_mapping" }, + "settings": { "__scope_link": "put_settings" } } } } diff --git a/src/core_plugins/console/api_server/spec/overrides/indices.update_aliases.json b/src/core_plugins/console/api_server/spec/overrides/indices.update_aliases.json index 4b695cc815dc9b..3d5c18e7d82d28 100644 --- a/src/core_plugins/console/api_server/spec/overrides/indices.update_aliases.json +++ b/src/core_plugins/console/api_server/spec/overrides/indices.update_aliases.json @@ -1,5 +1,5 @@ { - "_aliases": { + "indices.update_aliases": { "data_autocomplete_rules": { "actions": { "__template": [ diff --git a/src/core_plugins/console/api_server/spec/overrides/indices.validate_query.json b/src/core_plugins/console/api_server/spec/overrides/indices.validate_query.json index a08ae94d71a30b..4b13ad55ab61fa 100644 --- a/src/core_plugins/console/api_server/spec/overrides/indices.validate_query.json +++ b/src/core_plugins/console/api_server/spec/overrides/indices.validate_query.json @@ -1,5 +1,5 @@ { - "_upgrade": { + "indices.validate_query": { "data_autocomplete_rules": { "query": {} } diff --git a/src/core_plugins/console/index.js b/src/core_plugins/console/index.js index b02a331373538a..61a36e8a2a55e4 100644 --- a/src/core_plugins/console/index.js +++ b/src/core_plugins/console/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Boom from 'boom'; import { resolveApi } from './api_server/server'; import { existsSync } from 'fs'; diff --git a/src/core_plugins/console/public/.eslintrc b/src/core_plugins/console/public/.eslintrc deleted file mode 100644 index 1b226ba6bab8ce..00000000000000 --- a/src/core_plugins/console/public/.eslintrc +++ /dev/null @@ -1,32 +0,0 @@ ---- - -rules: - block-scoped-var: off - camelcase: off - curly: off - dot-location: off - dot-notation: off - eqeqeq: off - guard-for-in: off - indent: off - max-len: off - new-cap: off - no-caller: off - no-empty: off - no-extend-native: off - no-loop-func: off - no-multi-str: off - no-nested-ternary: off - no-proto: off - no-sequences: off - no-use-before-define: off - one-var: off - quotes: off - space-before-blocks: off - space-in-parens: off - space-infix-ops: off - semi: off - strict: off - wrap-iife: off - no-var: off - prefer-const: off diff --git a/src/core_plugins/console/public/console.js b/src/core_plugins/console/public/console.js index 5733823b5c5fbb..2499d3e5a88e24 100644 --- a/src/core_plugins/console/public/console.js +++ b/src/core_plugins/console/public/console.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import uiRoutes from 'ui/routes'; import template from './index.html'; diff --git a/src/core_plugins/console/public/hacks/register.js b/src/core_plugins/console/public/hacks/register.js index c9f94a64f8f082..92233b57c5f733 100644 --- a/src/core_plugins/console/public/hacks/register.js +++ b/src/core_plugins/console/public/hacks/register.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { DevToolsRegistryProvider } from 'ui/registry/dev_tools'; DevToolsRegistryProvider.register(() => ({ diff --git a/src/core_plugins/console/public/src/__tests__/app.js b/src/core_plugins/console/public/src/__tests__/app.js index 50b8763020229e..fec4d68964f0ce 100644 --- a/src/core_plugins/console/public/src/__tests__/app.js +++ b/src/core_plugins/console/public/src/__tests__/app.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import $ from 'jquery'; @@ -6,9 +25,10 @@ import mappings from '../mappings'; import init from '../app'; describe('app initialization', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); - let inputMock, outputMock; + let inputMock; + let outputMock; let ajaxDoneStub; beforeEach(() => { ajaxDoneStub = sinon.stub(); @@ -68,7 +88,7 @@ describe('app initialization', () => { url: 'https://api.github.com/content', dataType: 'text', kbnXsrfToken: false, - headers: { Accept: "application/vnd.github.v3.raw" } + headers: { Accept: 'application/vnd.github.v3.raw' } }); sinon.assert.calledTwice(inputMock.moveToNextRequestEdge); diff --git a/src/core_plugins/console/public/src/__tests__/utils.js b/src/core_plugins/console/public/src/__tests__/utils.js index eb3b6e6770dd5c..f1260fd8fa83f8 100644 --- a/src/core_plugins/console/public/src/__tests__/utils.js +++ b/src/core_plugins/console/public/src/__tests__/utils.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import utils from '../utils'; diff --git a/src/core_plugins/console/public/src/app.js b/src/core_plugins/console/public/src/app.js index cdfb159eaab3df..840944a0ccb0d2 100644 --- a/src/core_plugins/console/public/src/app.js +++ b/src/core_plugins/console/public/src/app.js @@ -1,7 +1,26 @@ -var $ = require('jquery'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ -let history = require('./history'); -let mappings = require('./mappings'); +const $ = require('jquery'); + +const history = require('./history'); +const mappings = require('./mappings'); export default function init(input, output, sourceLocation = 'stored') { $(document.body).removeClass('fouc'); @@ -11,13 +30,13 @@ export default function init(input, output, sourceLocation = 'stored') { if (content != null) { input.update(content); } - output.update(""); + output.update(''); } function loadSavedState() { - var previousSaveState = history.getSavedEditorState(); + const previousSaveState = history.getSavedEditorState(); - if (sourceLocation == "stored") { + if (sourceLocation === 'stored') { if (previousSaveState) { resetToValues(previousSaveState.content); } @@ -53,10 +72,10 @@ export default function init(input, output, sourceLocation = 'stored') { } function setupAutosave() { - var timer; - var saveDelay = 500; + let timer; + const saveDelay = 500; - input.getSession().on("change", function onChange() { + input.getSession().on('change', function onChange() { if (timer) { timer = clearTimeout(timer); } @@ -66,11 +85,11 @@ export default function init(input, output, sourceLocation = 'stored') { function saveCurrentState() { try { - var content = input.getValue(); + const content = input.getValue(); history.updateCurrentState(content); } catch (e) { - console.log("Ignoring saving error: " + e); + console.log('Ignoring saving error: ' + e); } } @@ -78,30 +97,30 @@ export default function init(input, output, sourceLocation = 'stored') { // chooses to restore a request from the history // PREVENTS history from needing to know about the input history.restoreFromHistory = function applyHistoryElem(req) { - var session = input.getSession(); - var pos = input.getCursorPosition(); - var prefix = ""; - var suffix = "\n"; + const session = input.getSession(); + let pos = input.getCursorPosition(); + let prefix = ''; + let suffix = '\n'; if (input.parser.isStartRequestRow(pos.row)) { pos.column = 0; - suffix += "\n"; + suffix += '\n'; } else if (input.parser.isEndRequestRow(pos.row)) { - var line = session.getLine(pos.row); + const line = session.getLine(pos.row); pos.column = line.length; - prefix = "\n\n"; + prefix = '\n\n'; } else if (input.parser.isInBetweenRequestsRow(pos.row)) { pos.column = 0; } else { pos = input.nextRequestEnd(pos); - prefix = "\n\n"; + prefix = '\n\n'; } - var s = prefix + req.method + " " + req.endpoint; + let s = prefix + req.method + ' ' + req.endpoint; if (req.data) { - s += "\n" + req.data; + s += '\n' + req.data; } s += suffix; diff --git a/src/core_plugins/console/public/src/autocomplete.js b/src/core_plugins/console/public/src/autocomplete.js index cc7bf905ba0ef3..b82955eb012798 100644 --- a/src/core_plugins/console/public/src/autocomplete.js +++ b/src/core_plugins/console/public/src/autocomplete.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { getTopLevelUrlCompleteComponents, getEndpointBodyCompleteComponents, @@ -9,24 +28,24 @@ import { populateContext } from './autocomplete/engine'; import { URL_PATH_END_MARKER } from './autocomplete/url_pattern_matcher'; import _ from 'lodash'; import ace from 'ace'; -import 'ace/ext-language_tools'; +import 'brace/ext/language_tools'; -var AceRange = ace.require('ace/range').Range; +const AceRange = ace.acequire('ace/range').Range; -var LAST_EVALUATED_TOKEN = null; +let LAST_EVALUATED_TOKEN = null; export default function (editor) { function isSeparatorToken(token) { switch ((token || {}).type) { - case "url.slash": - case "url.comma": - case "url.questionmark": - case "paren.lparen": - case "paren.rparen": - case "punctuation.colon": - case "punctuation.comma": - case "whitespace": + case 'url.slash': + case 'url.comma': + case 'url.questionmark': + case 'paren.lparen': + case 'paren.rparen': + case 'punctuation.colon': + case 'punctuation.comma': + case 'whitespace': return true; default: // standing on white space, quotes or another punctuation - no replacing @@ -36,9 +55,9 @@ export default function (editor) { function isUrlPathToken(token) { switch ((token || {}).type) { - case "url.slash": - case "url.comma": - case "url.part": + case 'url.slash': + case 'url.comma': + case 'url.part': return true; default: return false; @@ -47,11 +66,11 @@ export default function (editor) { function isUrlParamsToken(token) { switch ((token || {}).type) { - case "url.param": - case "url.equal": - case "url.value": - case "url.questionmark": - case "url.amp": + case 'url.param': + case 'url.equal': + case 'url.value': + case 'url.questionmark': + case 'url.amp': return true; default: return false; @@ -60,24 +79,24 @@ export default function (editor) { function getAutoCompleteValueFromToken(token) { switch ((token || {}).type) { - case "variable": - case "string": - case "text": - case "constant.numeric": - case "constant.language.boolean": + case 'variable': + case 'string': + case 'text': + case 'constant.numeric': + case 'constant.language.boolean': return token.value.replace(/"/g, ''); - case "method": - case "url.part": + case 'method': + case 'url.part': return token.value; default: // standing on white space, quotes or another punctuation - no replacing - return ""; + return ''; } } function addMetaToTermsList(list, meta, template) { return _.map(list, function (t) { - if (typeof t !== "object") { + if (typeof t !== 'object') { t = { name: t }; } return _.defaults(t, { meta: meta, template: template }); @@ -85,43 +104,43 @@ export default function (editor) { } function applyTerm(term) { - var session = editor.getSession(); + const session = editor.getSession(); - var context = term.context; + const context = term.context; // make sure we get up to date replacement info. - addReplacementInfoToContext(context, editor.getCursorPosition(), term.insert_value); + addReplacementInfoToContext(context, editor.getCursorPosition(), term.insertValue); - var termAsString; - if (context.autoCompleteType == "body") { - termAsString = typeof term.insert_value == "string" ? '"' + term.insert_value + '"' : term.insert_value + ""; - if (term.insert_value === "[" || term.insert_value === "{") { - termAsString = ""; + let termAsString; + if (context.autoCompleteType === 'body') { + termAsString = typeof term.insertValue === 'string' ? '"' + term.insertValue + '"' : term.insertValue + ''; + if (term.insertValue === '[' || term.insertValue === '{') { + termAsString = ''; } } else { - termAsString = term.insert_value + ""; + termAsString = term.insertValue + ''; } - var valueToInsert = termAsString; - var templateInserted = false; + let valueToInsert = termAsString; + let templateInserted = false; if (context.addTemplate && !_.isUndefined(term.template) && !_.isNull(term.template)) { - var indentedTemplateLines = utils.jsonToString(term.template, true).split("\n"); - var currentIndentation = session.getLine(context.rangeToReplace.start.row); + const indentedTemplateLines = utils.jsonToString(term.template, true).split('\n'); + let currentIndentation = session.getLine(context.rangeToReplace.start.row); currentIndentation = currentIndentation.match(/^\s*/)[0]; - for (var i = 1; i < indentedTemplateLines.length; i++) // skip first line - indentedTemplateLines[i] = currentIndentation + indentedTemplateLines[i]; + for (let i = 1; i < indentedTemplateLines.length; i++) // skip first line + {indentedTemplateLines[i] = currentIndentation + indentedTemplateLines[i];} - valueToInsert += ": " + indentedTemplateLines.join("\n"); + valueToInsert += ': ' + indentedTemplateLines.join('\n'); templateInserted = true; } else { templateInserted = true; - if (term.value === "[") { - valueToInsert += "[]"; + if (term.value === '[') { + valueToInsert += '[]'; } - else if (term.value == "{") { - valueToInsert += "{}"; + else if (term.value === '{') { + valueToInsert += '{}'; } else { templateInserted = false; @@ -133,7 +152,7 @@ export default function (editor) { // disable listening to the changes we are making. removeChangeListener(); - if (context.rangeToReplace.start.column != context.rangeToReplace.end.column) { + if (context.rangeToReplace.start.column !== context.rangeToReplace.end.column) { session.replace(context.rangeToReplace, valueToInsert); } else { @@ -143,24 +162,24 @@ export default function (editor) { editor.clearSelection(); // for some reason the above changes selection // go back to see whether we have one of ( : { & [ do not require a comma. All the rest do. - var newPos = { + let newPos = { row: context.rangeToReplace.start.row, column: context.rangeToReplace.start.column + termAsString.length + context.prefixToAdd.length + (templateInserted ? 0 : context.suffixToAdd.length) }; - var tokenIter = editor.iterForPosition(newPos.row, newPos.column); + const tokenIter = editor.iterForPosition(newPos.row, newPos.column); - if (context.autoCompleteType === "body") { + if (context.autoCompleteType === 'body') { // look for the next place stand, just after a comma, { - var nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - switch (nonEmptyToken ? nonEmptyToken.type : "NOTOKEN") { - case "paren.rparen": + let nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); + switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { + case 'paren.rparen': newPos = { row: tokenIter.getCurrentTokenRow(), column: tokenIter.getCurrentTokenColumn() }; break; - case "punctuation.colon": + case 'punctuation.colon': nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - if ((nonEmptyToken || {}).type == "paren.lparen") { + if ((nonEmptyToken || {}).type === 'paren.lparen') { nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); newPos = { row: tokenIter.getCurrentTokenRow(), column: tokenIter.getCurrentTokenColumn() }; if (nonEmptyToken && nonEmptyToken.value.indexOf('"') === 0) { @@ -168,8 +187,8 @@ export default function (editor) { } // don't stand on " } break; - case "paren.lparen": - case "punctuation.comma": + case 'paren.lparen': + case 'punctuation.comma': tokenIter.stepForward(); newPos = { row: tokenIter.getCurrentTokenRow(), column: tokenIter.getCurrentTokenColumn() }; break; @@ -183,7 +202,7 @@ export default function (editor) { function getAutoCompleteContext(editor, session, pos) { // deduces all the parameters need to position and insert the auto complete - var context = { + const context = { autoCompleteSet: null, // instructions for what can be here endpoint: null, urlPath: null, @@ -201,16 +220,16 @@ export default function (editor) { context.autoCompleteType = getAutoCompleteType(pos); switch (context.autoCompleteType) { - case "path": + case 'path': addPathAutoCompleteSetToContext(context, pos); break; - case "url_params": + case 'url_params': addUrlParamsAutoCompleteSetToContext(context, pos); break; - case "method": + case 'method': addMethodAutoCompleteSetToContext(context, pos); break; - case "body": + case 'body': addBodyAutoCompleteSetToContext(context, pos); break; default: @@ -231,48 +250,48 @@ export default function (editor) { function getAutoCompleteType(pos) { // return "method", "path" or "body" to determine auto complete type. - var rowMode = editor.parser.getRowParseMode(pos.row); + let rowMode = editor.parser.getRowParseMode(pos.row); //noinspection JSBitwiseOperatorUsage if (rowMode & editor.parser.MODE.IN_REQUEST) { - return "body"; + return 'body'; } //noinspection JSBitwiseOperatorUsage if (rowMode & editor.parser.MODE.REQUEST_START) { // on url path, url params or method. - var tokenIter = editor.iterForPosition(pos.row, pos.column); - var t = tokenIter.getCurrentToken(); + const tokenIter = editor.iterForPosition(pos.row, pos.column); + let t = tokenIter.getCurrentToken(); - while (t.type == "url.comma") { + while (t.type === 'url.comma') { t = tokenIter.stepBackward(); } switch (t.type) { - case "method": - return "method"; - case "whitespace": + case 'method': + return 'method'; + case 'whitespace': t = editor.parser.prevNonEmptyToken(tokenIter); switch ((t || {}).type) { - case "method": + case 'method': // we moved one back - return "path"; + return 'path'; break; default: if (isUrlPathToken(t)) { - return "path"; + return 'path'; } if (isUrlParamsToken(t)) { - return "url_params"; + return 'url_params'; } return null; } break; default: if (isUrlPathToken(t)) { - return "path"; + return 'path'; } if (isUrlParamsToken(t)) { - return "url_params"; + return 'url_params'; } return null; } @@ -281,19 +300,19 @@ export default function (editor) { // after start to avoid single line url only requests //noinspection JSBitwiseOperatorUsage if (rowMode & editor.parser.MODE.REQUEST_END) { - return "body" + return 'body'; } // in between request on an empty - if ((editor.getSession().getLine(pos.row) || "").trim() === "") { + if ((editor.getSession().getLine(pos.row) || '').trim() === '') { // check if the previous line is a single line begging of a new request rowMode = editor.parser.getRowParseMode(pos.row - 1); //noinspection JSBitwiseOperatorUsage if ((rowMode & editor.parser.MODE.REQUEST_START) && (rowMode & editor.parser.MODE.REQUEST_END)) { - return "body"; + return 'body'; } //o.w suggest a method - return "method"; + return 'method'; } return null; @@ -309,33 +328,33 @@ export default function (editor) { // - Broken scenario { , bla| // - Nice token, broken before: {, "bla" - var session = editor.getSession(); + const session = editor.getSession(); context.updatedForToken = _.clone(session.getTokenAt(pos.row, pos.column)); if (!context.updatedForToken) { - context.updatedForToken = { value: "", start: pos.column }; + context.updatedForToken = { value: '', start: pos.column }; } // empty line - var anchorToken = context.createdWithToken; + let anchorToken = context.createdWithToken; if (!anchorToken) { anchorToken = context.updatedForToken; } switch (context.updatedForToken.type) { - case "variable": - case "string": - case "text": - case "constant.numeric": - case "constant.language.boolean": - case "method": - case "url.index": - case "url.type": - case "url.id": - case "url.method": - case "url.endpoint": - case "url.part": - case "url.param": - case "url.value": + case 'variable': + case 'string': + case 'text': + case 'constant.numeric': + case 'constant.language.boolean': + case 'method': + case 'url.index': + case 'url.type': + case 'url.id': + case 'url.method': + case 'url.endpoint': + case 'url.part': + case 'url.param': + case 'url.value': context.rangeToReplace = new AceRange( pos.row, anchorToken.start, pos.row, context.updatedForToken.start + context.updatedForToken.value.length @@ -343,7 +362,7 @@ export default function (editor) { context.replacingToken = true; break; default: - if (replacingTerm && context.updatedForToken.value == replacingTerm) { + if (replacingTerm && context.updatedForToken.value === replacingTerm) { context.rangeToReplace = new AceRange( pos.row, anchorToken.start, pos.row, context.updatedForToken.start + context.updatedForToken.value.length @@ -363,16 +382,16 @@ export default function (editor) { context.textBoxPosition = { row: context.rangeToReplace.start.row, column: context.rangeToReplace.start.column }; switch (context.autoCompleteType) { - case "path": + case 'path': addPathPrefixSuffixToContext(context); break; - case "url_params": + case 'url_params': addUrlParamsPrefixSuffixToContext(context); break; - case "method": + case 'method': addMethodPrefixSuffixToContext(context); break; - case "body": + case 'body': addBodyPrefixSuffixToContext(context); break; } @@ -384,28 +403,28 @@ export default function (editor) { // Templates will be used if not destroying existing structure. // -> token : {} or token ]/} or token , but not token : SOMETHING ELSE - context.prefixToAdd = ""; - context.suffixToAdd = ""; + context.prefixToAdd = ''; + context.suffixToAdd = ''; - var tokenIter = editor.iterForCurrentLoc(); - var nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - switch (nonEmptyToken ? nonEmptyToken.type : "NOTOKEN") { - case "NOTOKEN": - case "paren.lparen": - case "paren.rparen": - case "punctuation.comma": + let tokenIter = editor.iterForCurrentLoc(); + let nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); + switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { + case 'NOTOKEN': + case 'paren.lparen': + case 'paren.rparen': + case 'punctuation.comma': context.addTemplate = true; break; - case "punctuation.colon": + case 'punctuation.colon': // test if there is an empty object - if so we replace it context.addTemplate = false; nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - if (!(nonEmptyToken && nonEmptyToken.value == "{")) { + if (!(nonEmptyToken && nonEmptyToken.value === '{')) { break; } nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - if (!(nonEmptyToken && nonEmptyToken.value == "}")) { + if (!(nonEmptyToken && nonEmptyToken.value === '}')) { break; } context.addTemplate = true; @@ -415,33 +434,33 @@ export default function (editor) { // move one more time to check if we need a trailing comma nonEmptyToken = editor.parser.nextNonEmptyToken(tokenIter); - switch (nonEmptyToken ? nonEmptyToken.type : "NOTOKEN") { - case "NOTOKEN": - case "paren.rparen": - case "punctuation.comma": - case "punctuation.colon": + switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { + case 'NOTOKEN': + case 'paren.rparen': + case 'punctuation.comma': + case 'punctuation.colon': break; default: - context.suffixToAdd = ", " + context.suffixToAdd = ', '; } break; default: context.addTemplate = true; - context.suffixToAdd = ", "; + context.suffixToAdd = ', '; break; // for now play safe and do nothing. May be made smarter. } // go back to see whether we have one of ( : { & [ do not require a comma. All the rest do. tokenIter = editor.iterForCurrentLoc(); nonEmptyToken = tokenIter.getCurrentToken(); - var insertingRelativeToToken; // -1 is before token, 0 middle, +1 after token + let insertingRelativeToToken; // -1 is before token, 0 middle, +1 after token if (context.replacingToken) { insertingRelativeToToken = 0; } else { - var pos = editor.getCursorPosition(); - if (pos.column == context.updatedForToken.start) { + const pos = editor.getCursorPosition(); + if (pos.column === context.updatedForToken.start) { insertingRelativeToToken = -1; } else if (pos.column < context.updatedForToken.start + context.updatedForToken.value.length) { @@ -457,16 +476,16 @@ export default function (editor) { nonEmptyToken = editor.parser.prevNonEmptyToken(tokenIter); } - switch (nonEmptyToken ? nonEmptyToken.type : "NOTOKEN") { - case "NOTOKEN": - case "paren.lparen": - case "punctuation.comma": - case "punctuation.colon": - case "method": + switch (nonEmptyToken ? nonEmptyToken.type : 'NOTOKEN') { + case 'NOTOKEN': + case 'paren.lparen': + case 'punctuation.comma': + case 'punctuation.colon': + case 'method': break; default: - if (nonEmptyToken && nonEmptyToken.type.indexOf("url") < 0) { - context.prefixToAdd = ", " + if (nonEmptyToken && nonEmptyToken.type.indexOf('url') < 0) { + context.prefixToAdd = ', '; } } @@ -474,30 +493,30 @@ export default function (editor) { } function addUrlParamsPrefixSuffixToContext(context) { - context.prefixToAdd = ""; - context.suffixToAdd = ""; + context.prefixToAdd = ''; + context.suffixToAdd = ''; } function addMethodPrefixSuffixToContext(context) { - context.prefixToAdd = ""; - context.suffixToAdd = ""; - var tokenIter = editor.iterForCurrentLoc(); - var row = tokenIter.getCurrentTokenRow(); - var t = editor.parser.nextNonEmptyToken(tokenIter); + context.prefixToAdd = ''; + context.suffixToAdd = ''; + const tokenIter = editor.iterForCurrentLoc(); + const row = tokenIter.getCurrentTokenRow(); + const t = editor.parser.nextNonEmptyToken(tokenIter); - if (tokenIter.getCurrentTokenRow() != row || !t) { + if (tokenIter.getCurrentTokenRow() !== row || !t) { // we still have nothing next to the method, add a space.. - context.suffixToAdd = " "; + context.suffixToAdd = ' '; } } function addPathPrefixSuffixToContext(context) { - context.prefixToAdd = ""; - context.suffixToAdd = ""; + context.prefixToAdd = ''; + context.suffixToAdd = ''; } function addMethodAutoCompleteSetToContext(context) { - context.autoCompleteSet = ["GET", "PUT", "POST", "DELETE", "HEAD"].map((m, i) => ({ + context.autoCompleteSet = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'].map((m, i) => ({ name: m, score: -i, meta: 'method' @@ -505,38 +524,39 @@ export default function (editor) { } function addPathAutoCompleteSetToContext(context, pos) { - var ret = getCurrentMethodAndTokenPaths(pos); + const ret = getCurrentMethodAndTokenPaths(pos); context.method = ret.method; context.token = ret.token; context.otherTokenValues = ret.otherTokenValues; context.urlTokenPath = ret.urlTokenPath; populateContext(ret.urlTokenPath, context, editor, true, getTopLevelUrlCompleteComponents()); - context.autoCompleteSet = addMetaToTermsList(context.autoCompleteSet, "endpoint"); + context.autoCompleteSet = addMetaToTermsList(context.autoCompleteSet, 'endpoint'); } function addUrlParamsAutoCompleteSetToContext(context, pos) { - var ret = getCurrentMethodAndTokenPaths(pos); + const ret = getCurrentMethodAndTokenPaths(pos); context.method = ret.method; context.otherTokenValues = ret.otherTokenValues; context.urlTokenPath = ret.urlTokenPath; if (!ret.urlTokenPath) { // zero length tokenPath is true - console.log("Can't extract a valid url token path."); + console.log('Can\'t extract a valid url token path.'); return context; } populateContext(ret.urlTokenPath, context, editor, false, getTopLevelUrlCompleteComponents()); if (!context.endpoint) { - console.log("couldn't resolve an endpoint."); + console.log('couldn\'t resolve an endpoint.'); return context; } if (!ret.urlParamsTokenPath) { // zero length tokenPath is true - console.log("Can't extract a valid urlParams token path."); + console.log('Can\'t extract a valid urlParams token path.'); return context; } - var tokenPath = [], currentParam = ret.urlParamsTokenPath.pop(); + let tokenPath = []; + const currentParam = ret.urlParamsTokenPath.pop(); if (currentParam) { tokenPath = Object.keys(currentParam); // single key object context.otherTokenValues = currentParam[tokenPath[0]]; @@ -549,13 +569,13 @@ export default function (editor) { function addBodyAutoCompleteSetToContext(context, pos) { - var ret = getCurrentMethodAndTokenPaths(pos); + const ret = getCurrentMethodAndTokenPaths(pos); context.method = ret.method; context.otherTokenValues = ret.otherTokenValues; context.urlTokenPath = ret.urlTokenPath; context.requestStartRow = ret.requestStartRow; if (!ret.urlTokenPath) { // zero length tokenPath is true - console.log("Can't extract a valid url token path."); + console.log('Can\'t extract a valid url token path.'); return context; } @@ -564,14 +584,14 @@ export default function (editor) { context.bodyTokenPath = ret.bodyTokenPath; if (!ret.bodyTokenPath) { // zero length tokenPath is true - console.log("Can't extract a valid body token path."); + console.log('Can\'t extract a valid body token path.'); return context; } // needed for scope linking + global term resolving context.endpointComponentResolver = getEndpointBodyCompleteComponents; context.globalComponentResolver = getGlobalAutocompleteComponents; - var components; + let components; if (context.endpoint) { components = context.endpoint.bodyAutocompleteRootComponents; } @@ -584,21 +604,22 @@ export default function (editor) { } function getCurrentMethodAndTokenPaths(pos) { - var tokenIter = editor.iterForPosition(pos.row, pos.column); - var startPos = pos; - var bodyTokenPath = [], ret = {}; + const tokenIter = editor.iterForPosition(pos.row, pos.column); + const startPos = pos; + let bodyTokenPath = []; + const ret = {}; - var STATES = { + const STATES = { looking_for_key: 0, // looking for a key but without jumping over anything but white space and colon. looking_for_scope_start: 1, // skip everything until scope start start: 3 }; - var state = STATES.start; + let state = STATES.start; // initialization problems - - var t = tokenIter.getCurrentToken(); + let t = tokenIter.getCurrentToken(); if (t) { - if (startPos.column == 0) { + if (startPos.column === 0) { // if we are at the beginning of the line, the current token is the one after cursor, not before which // deviates from the standard. t = tokenIter.stepBackward(); @@ -606,49 +627,49 @@ export default function (editor) { } } else { - if (startPos.column == 0) { + if (startPos.column === 0) { // empty lines do no have tokens, move one back t = tokenIter.stepBackward(); state = STATES.start; } } - var walkedSomeBody = false; + let walkedSomeBody = false; // climb one scope at a time and get the scope key - for (; t && t.type.indexOf("url") == -1 && t.type != "method"; t = tokenIter.stepBackward()) { + for (; t && t.type.indexOf('url') === -1 && t.type !== 'method'; t = tokenIter.stepBackward()) { - if (t.type != "whitespace") { + if (t.type !== 'whitespace') { walkedSomeBody = true; } // marks we saw something switch (t.type) { - case "variable": - if (state == STATES.looking_for_key) { + case 'variable': + if (state === STATES.looking_for_key) { bodyTokenPath.unshift(t.value.trim().replace(/"/g, '')); } state = STATES.looking_for_scope_start; // skip everything until the beginning of this scope break; - case "paren.lparen": + case 'paren.lparen': bodyTokenPath.unshift(t.value); - if (state == STATES.looking_for_scope_start) { + if (state === STATES.looking_for_scope_start) { // found it. go look for the relevant key state = STATES.looking_for_key; } break; - case "paren.rparen": + case 'paren.rparen': // reset he search for key state = STATES.looking_for_scope_start; // and ignore this sub scope.. - var parenCount = 1; + let parenCount = 1; t = tokenIter.stepBackward(); while (t && parenCount > 0) { switch (t.type) { - case "paren.lparen": + case 'paren.lparen': parenCount--; break; - case "paren.rparen": + case 'paren.rparen': parenCount++; break; } @@ -661,13 +682,13 @@ export default function (editor) { return {}; } continue; - case "punctuation.end_triple_quote": + case 'punctuation.end_triple_quote': // reset the search for key state = STATES.looking_for_scope_start; for (t = tokenIter.stepBackward(); t; t = tokenIter.stepBackward()) { - if (t.type === "punctuation.start_tripple_qoute") { - t = tokenIter.stepBackward(); - break; + if (t.type === 'punctuation.start_tripple_qoute') { + t = tokenIter.stepBackward(); + break; } } if (!t) // oops we run out.. we don't know what's up return null; @@ -675,35 +696,35 @@ export default function (editor) { return {}; } continue; - case "punctuation.start_triple_quote": - if (state == STATES.start) { + case 'punctuation.start_triple_quote': + if (state === STATES.start) { state = STATES.looking_for_key; } - else if (state == STATES.looking_for_key) { + else if (state === STATES.looking_for_key) { state = STATES.looking_for_scope_start; } bodyTokenPath.unshift('"""'); continue; - case "string": - case "constant.numeric": - case "constant.language.boolean": - case "text": - if (state == STATES.start) { + case 'string': + case 'constant.numeric': + case 'constant.language.boolean': + case 'text': + if (state === STATES.start) { state = STATES.looking_for_key; } - else if (state == STATES.looking_for_key) { + else if (state === STATES.looking_for_key) { state = STATES.looking_for_scope_start; } break; - case "punctuation.comma": - if (state == STATES.start) { + case 'punctuation.comma': + if (state === STATES.start) { state = STATES.looking_for_scope_start; } break; - case "punctuation.colon": - case "whitespace": - if (state == STATES.start) { + case 'punctuation.colon': + case 'whitespace': + if (state === STATES.start) { state = STATES.looking_for_key; } break; // skip white space @@ -711,13 +732,13 @@ export default function (editor) { } } - if (walkedSomeBody && (!bodyTokenPath || bodyTokenPath.length == 0)) { + if (walkedSomeBody && (!bodyTokenPath || bodyTokenPath.length === 0)) { // we had some content and still no path -> the cursor is position after a closed body -> no auto complete return {}; } - if (tokenIter.getCurrentTokenRow() == startPos.row) { - if (t.type === "url.part" || t.type === "url.param" || t.type === "url.value") { + if (tokenIter.getCurrentTokenRow() === startPos.row) { + if (t.type === 'url.part' || t.type === 'url.param' || t.type === 'url.value') { // we are on the same line as cursor and dealing with a url. Current token is not part of the context t = tokenIter.stepBackward(); } @@ -728,11 +749,11 @@ export default function (editor) { ret.urlTokenPath = []; ret.urlParamsTokenPath = null; ret.requestStartRow = tokenIter.getCurrentTokenRow(); - var curUrlPart; + let curUrlPart; while (t && isUrlParamsToken(t)) { switch (t.type) { - case "url.value": + case 'url.value': if (Array.isArray(curUrlPart)) { curUrlPart.unshift(t.value); } @@ -743,7 +764,7 @@ export default function (editor) { curUrlPart = t.value; } break; - case "url.comma": + case 'url.comma': if (!curUrlPart) { curUrlPart = []; } @@ -751,13 +772,13 @@ export default function (editor) { curUrlPart = [curUrlPart]; } break; - case "url.param": - var v = curUrlPart; + case 'url.param': + const v = curUrlPart; curUrlPart = {}; curUrlPart[t.value] = v; break; - case "url.amp": - case "url.questionmark": + case 'url.amp': + case 'url.questionmark': if (!ret.urlParamsTokenPath) { ret.urlParamsTokenPath = []; } @@ -769,9 +790,9 @@ export default function (editor) { } curUrlPart = null; - while (t && t.type.indexOf("url") != -1) { + while (t && t.type.indexOf('url') !== -1) { switch (t.type) { - case "url.part": + case 'url.part': if (Array.isArray(curUrlPart)) { curUrlPart.unshift(t.value); } @@ -782,7 +803,7 @@ export default function (editor) { curUrlPart = t.value; } break; - case "url.comma": + case 'url.comma': if (!curUrlPart) { curUrlPart = []; } @@ -790,7 +811,7 @@ export default function (editor) { curUrlPart = [curUrlPart]; } break; - case "url.slash": + case 'url.slash': ret.urlTokenPath.unshift(curUrlPart); curUrlPart = null; break; @@ -814,28 +835,28 @@ export default function (editor) { ret.urlTokenPath.push(URL_PATH_END_MARKER); } - if (t && t.type == "method") { + if (t && t.type === 'method') { ret.method = t.value; } return ret; } - var evaluateCurrentTokenAfterAChange = _.debounce(function evaluateCurrentTokenAfterAChange(pos) { - var session = editor.getSession(); - var currentToken = session.getTokenAt(pos.row, pos.column); + const evaluateCurrentTokenAfterAChange = _.debounce(function evaluateCurrentTokenAfterAChange(pos) { + const session = editor.getSession(); + let currentToken = session.getTokenAt(pos.row, pos.column); if (!currentToken) { - if (pos.row == 0) { + if (pos.row === 0) { LAST_EVALUATED_TOKEN = null; return; } - currentToken = { start: 0, value: "" }; // empty row + currentToken = { start: 0, value: '' }; // empty row } currentToken.row = pos.row; // extend token with row. Ace doesn't supply it by default if (editor.parser.isEmptyToken(currentToken)) { // empty token. check what's coming next - var nextToken = session.getTokenAt(pos.row, pos.column + 1); + const nextToken = session.getTokenAt(pos.row, pos.column + 1); if (editor.parser.isEmptyToken(nextToken)) { // Empty line, or we're not on the edge of current token. Save the current position as base currentToken.start = pos.column; @@ -853,7 +874,7 @@ export default function (editor) { return; // wait for the next typing. } - if (LAST_EVALUATED_TOKEN.start != currentToken.start || LAST_EVALUATED_TOKEN.row != currentToken.row + if (LAST_EVALUATED_TOKEN.start !== currentToken.start || LAST_EVALUATED_TOKEN.row !== currentToken.row || LAST_EVALUATED_TOKEN.value === currentToken.value) { // not on the same place or nothing changed, cache and wait for the next time LAST_EVALUATED_TOKEN = currentToken; @@ -861,21 +882,21 @@ export default function (editor) { } // don't automatically open the auto complete if some just hit enter (new line) or open a parentheses - switch (currentToken.type || "UNKNOWN") { - case "paren.lparen": - case "paren.rparen": - case "punctuation.colon": - case "punctuation.comma": - case "UNKOWN": + switch (currentToken.type || 'UNKNOWN') { + case 'paren.lparen': + case 'paren.rparen': + case 'punctuation.colon': + case 'punctuation.comma': + case 'UNKOWN': return; } LAST_EVALUATED_TOKEN = currentToken; - editor.execCommand("startAutocomplete"); + editor.execCommand('startAutocomplete'); }, 100); function editorChangeListener() { - var cursor = editor.selection.lead; + const cursor = editor.selection.lead; if (editor.__ace.completer && editor.__ace.completer.activated) { return; } @@ -883,33 +904,33 @@ export default function (editor) { } function addChangeListener() { - editor.on("changeSelection", editorChangeListener); + editor.on('changeSelection', editorChangeListener); } function removeChangeListener() { - editor.off("changeSelection", editorChangeListener) + editor.off('changeSelection', editorChangeListener); } function getCompletions(aceEditor, session, pos, prefix, callback) { try { - var context = getAutoCompleteContext(editor, session, pos); + const context = getAutoCompleteContext(editor, session, pos); if (!context) { callback(null, []); } else { - var terms = _.map(context.autoCompleteSet, function (term) { - if (typeof term !== "object") { + const terms = _.map(context.autoCompleteSet, function (term) { + if (typeof term !== 'object') { term = { name: term - } + }; } else { term = _.clone(term); } return _.defaults(term, { value: term.name, - meta: "API", + meta: 'API', score: 0, context: context, completer: { @@ -939,7 +960,7 @@ export default function (editor) { }); callback(null, _.map(terms, function (t, i) { - t.insert_value = t.insert_value || t.value; + t.insertValue = t.insertValue || t.value; t.value = '' + t.value; // normalize to strings t.score = -i; return t; @@ -947,7 +968,7 @@ export default function (editor) { } } catch (e) { - console.log("error while getting completion terms", e); + console.log('error while getting completion terms', e); callback(e, null); } } @@ -963,32 +984,33 @@ export default function (editor) { }; }); - var langTools = ace.require('ace/ext/language_tools'); - var aceUtils = ace.require('ace/autocomplete/util'); - var aceAutoComplete = ace.require('ace/autocomplete'); + const langTools = ace.acequire('ace/ext/language_tools'); + const aceUtils = ace.acequire('ace/autocomplete/util'); + const aceAutoComplete = ace.acequire('ace/autocomplete'); - langTools.addCompleter({ + langTools.setCompleters([{ getCompletions: getCompletions - }); + }]); editor.setOptions({ enableBasicAutocompletion: true }); - + editor.$blockScrolling = Infinity; // Ace doesn't care about tokenization when calculating prefix. It will thus stop on . in keys names. // we patch this behavior. // CHECK ON ACE UPDATE - var aceAutoCompleteInstance = new aceAutoComplete.Autocomplete(); + const aceAutoCompleteInstance = new aceAutoComplete.Autocomplete(); aceAutoCompleteInstance.autoInsert = false; - aceAutoCompleteInstance.gatherCompletions = function (ace_editor, callback) { - var session = ace_editor.getSession(); - var pos = ace_editor.getCursorPosition(); - var prefix = ""; + aceAutoCompleteInstance.gatherCompletions = function (aceEditor, callback) { + const session = aceEditor.getSession(); + const pos = aceEditor.getCursorPosition(); + let prefix = ''; // change starts here - var token = session.getTokenAt(pos.row, pos.column); + const token = session.getTokenAt(pos.row, pos.column); this.base = _.clone(pos); + this.base.detach = () => {}; if (!editor.parser.isEmptyToken(token) && !isSeparatorToken(token)) { - if (token.value.indexOf('"') == 0) { + if (token.value.indexOf('"') === 0) { this.base.column = token.start + 1; } else { @@ -998,9 +1020,9 @@ export default function (editor) { prefix = getAutoCompleteValueFromToken(token); } - var matches = []; - aceUtils.parForEach(ace_editor.completers, function (completer, next) { - completer.getCompletions(ace_editor, session, pos, prefix, function (err, results) { + let matches = []; + aceUtils.parForEach(aceEditor.completers, function (completer, next) { + completer.getCompletions(aceEditor, session, pos, prefix, function (err, results) { if (!err) { matches = matches.concat(results); } @@ -1024,5 +1046,5 @@ export default function (editor) { addChangeListener: addChangeListener, removeChangeListener: removeChangeListener } - } + }; } diff --git a/src/core_plugins/console/public/src/autocomplete/body_completer.js b/src/core_plugins/console/public/src/autocomplete/body_completer.js index b69686b2da79f0..55d325ddc82aab 100644 --- a/src/core_plugins/console/public/src/autocomplete/body_completer.js +++ b/src/core_plugins/console/public/src/autocomplete/body_completer.js @@ -1,9 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const _ = require('lodash'); const engine = require('./engine'); -function CompilingContext(endpoint_id, parametrizedComponentFactories) { +function CompilingContext(endpointId, parametrizedComponentFactories) { this.parametrizedComponentFactories = parametrizedComponentFactories; - this.endpoint_id = endpoint_id; + this.endpointId = endpointId; } function getTemplate(description) { @@ -21,10 +40,10 @@ function getTemplate(description) { return {}; } else if (Array.isArray(description)) { - if (description.length == 1) { + if (description.length === 1) { if (_.isObject(description[0])) { // shortcut to save typing - var innerTemplate = getTemplate(description[0]); + const innerTemplate = getTemplate(description[0]); return innerTemplate != null ? [innerTemplate] : []; } @@ -43,8 +62,8 @@ function getTemplate(description) { } function getOptions(description) { - var options = {}; - var template = getTemplate(description); + const options = {}; + const template = getTemplate(description); if (!_.isUndefined(template)) { options.template = template; @@ -63,7 +82,7 @@ function compileDescription(description, compilingContext) { else if (_.isObject(description)) { // test for objects list as arrays are also objects if (description.__scope_link) { - return [new ScopeResolver(description.__scope_link, compilingContext)] + return [new ScopeResolver(description.__scope_link, compilingContext)]; } if (description.__any_of) { return [compileList(description.__any_of, compilingContext)]; @@ -73,7 +92,7 @@ function compileDescription(description, compilingContext) { return compileDescription(d, compilingContext); })); } - let obj = compileObject(description, compilingContext); + const obj = compileObject(description, compilingContext); if (description.__condition) { return [compileCondition(description.__condition, obj, compilingContext)]; } else { @@ -91,9 +110,9 @@ function compileDescription(description, compilingContext) { function compileParametrizedValue(value, compilingContext, template) { value = value.substr(1, value.length - 2).toLowerCase(); - var component = compilingContext.parametrizedComponentFactories[value]; + let component = compilingContext.parametrizedComponentFactories[value]; if (!component) { - throw new Error("no factory found for '" + value + "'"); + throw new Error('no factory found for \'' + value + '\''); } component = component(value, null, template); if (!_.isUndefined(template)) { @@ -104,20 +123,22 @@ function compileParametrizedValue(value, compilingContext, template) { } function compileObject(objDescription, compilingContext) { - var objectC = new engine.ConstantComponent("{"); - var constants = [], patterns = []; + const objectC = new engine.ConstantComponent('{'); + const constants = []; + const patterns = []; _.each(objDescription, function (desc, key) { - if (key.indexOf("__") == 0) { + if (key.indexOf('__') === 0) { // meta key return; } - var options = getOptions(desc), component; + const options = getOptions(desc); + let component; if (/^\{.*\}$/.test(key)) { component = compileParametrizedValue(key, compilingContext, options.template); patterns.push(component); } - else if (key === "*") { + else if (key === '*') { component = new engine.SharedComponent(key); patterns.push(component); } @@ -130,12 +151,12 @@ function compileObject(objDescription, compilingContext) { component.addComponent(subComponent); }); }); - objectC.addComponent(new ObjectComponent("inner", constants, patterns)); + objectC.addComponent(new ObjectComponent('inner', constants, patterns)); return objectC; } function compileList(listRule, compilingContext) { - var listC = new engine.ConstantComponent("["); + const listC = new engine.ConstantComponent('['); _.each(listRule, function (desc) { _.each(compileDescription(desc, compilingContext), function (component) { listC.addComponent(component); @@ -148,11 +169,11 @@ function compileList(listRule, compilingContext) { function compileCondition(description, compiledObject) { if (description.lines_regex) { return new ConditionalProxy(function (context, editor) { - let lines = editor.getSession().getLines(context.requestStartRow, editor.getCursorPosition().row).join("\n"); - return new RegExp(description.lines_regex, "m").test(lines); + const lines = editor.getSession().getLines(context.requestStartRow, editor.getCursorPosition().row).join('\n'); + return new RegExp(description.lines_regex, 'm').test(lines); }, compiledObject); } else { - throw "unknown condition type - got: " + JSON.stringify(description); + throw 'unknown condition type - got: ' + JSON.stringify(description); } } @@ -174,7 +195,7 @@ ObjectComponent.prototype = _.create( (function (cls) { cls.getTerms = function (context, editor) { - var options = []; + const options = []; _.each(this.constants, function (component) { options.push.apply(options, component.getTerms(context, editor)); }); @@ -185,18 +206,18 @@ ObjectComponent.prototype = _.create( }; cls.match = function (token, context, editor) { - var result = { + const result = { next: [] }; _.each(this.constants, function (component) { - var componentResult = component.match(token, context, editor); + const componentResult = component.match(token, context, editor); if (componentResult && componentResult.next) { result.next.push.apply(result.next, componentResult.next); } }); // try to link to GLOBAL rules - var globalRules = context.globalComponentResolver(token, false); + const globalRules = context.globalComponentResolver(token, false); if (globalRules) { result.next.push.apply(result.next, globalRules); } @@ -205,7 +226,7 @@ ObjectComponent.prototype = _.create( return result; } _.each(this.patternsAndWildCards, function (component) { - var componentResult = component.match(token, context, editor); + const componentResult = component.match(token, context, editor); if (componentResult && componentResult.next) { result.next.push.apply(result.next, componentResult.next); } @@ -214,7 +235,7 @@ ObjectComponent.prototype = _.create( return result; }; -})(ObjectComponent.prototype); +}(ObjectComponent.prototype)); /** * An object to resolve scope links (syntax endpoint.path1.path2) @@ -228,14 +249,14 @@ ObjectComponent.prototype = _.create( * which should return the top level components for the given endpoint */ function ScopeResolver(link, compilingContext) { - engine.SharedComponent.call(this, "__scope_link", null); - if (_.isString(link) && link[0] === ".") { + engine.SharedComponent.call(this, '__scope_link', null); + if (_.isString(link) && link[0] === '.') { // relative link, inject current endpoint - if (link === ".") { - link = compilingContext.endpoint_id; + if (link === '.') { + link = compilingContext.endpointId; } else { - link = compilingContext.endpoint_id + link; + link = compilingContext.endpointId + link; } } this.link = link; @@ -251,23 +272,23 @@ ScopeResolver.prototype = _.create( cls.resolveLinkToComponents = function (context, editor) { if (_.isFunction(this.link)) { - var desc = this.link(context, editor); + const desc = this.link(context, editor); return compileDescription(desc, this.compilingContext); } if (!_.isString(this.link)) { - throw new Error("unsupported link format", this.link); + throw new Error('unsupported link format', this.link); } - var path = this.link.replace(/\./g, "{").split(/(\{)/); - var endpoint = path[0]; - var components; + let path = this.link.replace(/\./g, '{').split(/(\{)/); + const endpoint = path[0]; + let components; try { - if (endpoint === "GLOBAL") { + if (endpoint === 'GLOBAL') { // global rules need an extra indirection if (path.length < 3) { - throw new Error("missing term in global link: " + this.link); + throw new Error('missing term in global link: ' + this.link); } - var term = path[2]; + const term = path[2]; components = context.globalComponentResolver(term); path = path.slice(3); } @@ -277,13 +298,14 @@ ScopeResolver.prototype = _.create( } } catch (e) { - throw new Error("failed to resolve link [" + this.link + "]: " + e); + throw new Error('failed to resolve link [' + this.link + ']: ' + e); } return engine.resolvePathToComponents(path, context, editor, components); }; cls.getTerms = function (context, editor) { - var options = [], components = this.resolveLinkToComponents(context, editor); + const options = []; + const components = this.resolveLinkToComponents(context, editor); _.each(components, function (component) { options.push.apply(options, component.getTerms(context, editor)); }); @@ -291,13 +313,13 @@ ScopeResolver.prototype = _.create( }; cls.match = function (token, context, editor) { - var result = { - next: [] - }, - components = this.resolveLinkToComponents(context, editor); + const result = { + next: [] + }; + const components = this.resolveLinkToComponents(context, editor); _.each(components, function (component) { - var componentResult = component.match(token, context, editor); + const componentResult = component.match(token, context, editor); if (componentResult && componentResult.next) { result.next.push.apply(result.next, componentResult.next); } @@ -305,11 +327,11 @@ ScopeResolver.prototype = _.create( return result; }; -})(ScopeResolver.prototype); +}(ScopeResolver.prototype)); function ConditionalProxy(predicate, delegate) { - engine.SharedComponent.call(this, "__condition", null); + engine.SharedComponent.call(this, '__condition', null); this.predicate = predicate; this.delegate = delegate; } @@ -336,7 +358,7 @@ ConditionalProxy.prototype = _.create( return false; } }; -})(ConditionalProxy.prototype); +}(ConditionalProxy.prototype)); function GlobalOnlyComponent(name) { @@ -355,12 +377,12 @@ GlobalOnlyComponent.prototype = _.create( }; cls.match = function (token, context) { - var result = { + const result = { next: [] }; // try to link to GLOBAL rules - var globalRules = context.globalComponentResolver(token, false); + const globalRules = context.globalComponentResolver(token, false); if (globalRules) { result.next.push.apply(result.next, globalRules); } @@ -374,16 +396,16 @@ GlobalOnlyComponent.prototype = _.create( return result; }; -})(GlobalOnlyComponent.prototype); +}(GlobalOnlyComponent.prototype)); // a list of component that match anything but give auto complete suggestions based on global API entries. export function globalsOnlyAutocompleteComponents() { - return [new GlobalOnlyComponent("__global__")]; + return [new GlobalOnlyComponent('__global__')]; } /** - * @param endpoint_id id of the endpoint being compiled. + * @param endpointId id of the endpoint being compiled. * @param description a json dict describing the endpoint * @param endpointComponentResolver a function (endpoint,context,editor) which should resolve an endpoint * to it's list of compiled components. @@ -395,6 +417,6 @@ export function globalsOnlyAutocompleteComponents() { * } * } */ -export function compileBodyDescription(endpoint_id, description, parametrizedComponentFactories) { - return compileDescription(description, new CompilingContext(endpoint_id, parametrizedComponentFactories)); +export function compileBodyDescription(endpointId, description, parametrizedComponentFactories) { + return compileDescription(description, new CompilingContext(endpointId, parametrizedComponentFactories)); } diff --git a/src/core_plugins/console/public/src/autocomplete/engine.js b/src/core_plugins/console/public/src/autocomplete/engine.js index 96ffa1bd242cd7..23f0d990116c86 100644 --- a/src/core_plugins/console/public/src/autocomplete/engine.js +++ b/src/core_plugins/console/public/src/autocomplete/engine.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const _ = require('lodash'); export function AutocompleteComponent(name) { @@ -48,44 +67,44 @@ SharedComponent.prototype = _.create( }; cls.addComponent = function (component) { - var current = this._nextDict[component.name] || []; + const current = this._nextDict[component.name] || []; current.push(component); this._nextDict[component.name] = current; this.next = [].concat.apply([], _.values(this._nextDict)); }; -})(SharedComponent.prototype); +}(SharedComponent.prototype)); /** A component that suggests one of the give options, but accepts anything */ -function ListComponent(name, list, parent, multi_valued, allow_non_valid_values) { +function ListComponent(name, list, parent, multiValued, allowNonValidValues) { SharedComponent.call(this, name, parent); this.listGenerator = Array.isArray(list) ? function () { - return list + return list; } : list; - this.multi_valued = _.isUndefined(multi_valued) ? true : multi_valued; - this.allow_non_valid_values = _.isUndefined(allow_non_valid_values) ? false : allow_non_valid_values; + this.multiValued = _.isUndefined(multiValued) ? true : multiValued; + this.allowNonValidValues = _.isUndefined(allowNonValidValues) ? false : allowNonValidValues; } -ListComponent.prototype = _.create(SharedComponent.prototype, { "constructor": ListComponent }); +ListComponent.prototype = _.create(SharedComponent.prototype, { 'constructor': ListComponent }); (function (cls) { cls.getTerms = function (context, editor) { - if (!this.multi_valued && context.otherTokenValues) { + if (!this.multiValued && context.otherTokenValues) { // already have a value -> no suggestions - return [] + return []; } - var already_set = context.otherTokenValues || []; - if (_.isString(already_set)) { - already_set = [already_set]; + let alreadySet = context.otherTokenValues || []; + if (_.isString(alreadySet)) { + alreadySet = [alreadySet]; } - var ret = _.difference(this.listGenerator(context, editor), already_set); + let ret = _.difference(this.listGenerator(context, editor), alreadySet); if (this.getDefaultTermMeta()) { - var meta = this.getDefaultTermMeta(); + const meta = this.getDefaultTermMeta(); ret = _.map(ret, function (term) { if (_.isString(term)) { - term = { "name": term }; + term = { 'name': term }; } return _.defaults(term, { meta: meta }); }); @@ -95,17 +114,17 @@ ListComponent.prototype = _.create(SharedComponent.prototype, { "constructor": L }; cls.validateTokens = function (tokens) { - if (!this.multi_valued && tokens.length > 1) { + if (!this.multiValued && tokens.length > 1) { return false; } // verify we have all tokens - var list = this.listGenerator(); - var not_found = _.any(tokens, function (token) { - return list.indexOf(token) == -1; + const list = this.listGenerator(); + const notFound = _.any(tokens, function (token) { + return list.indexOf(token) === -1; }); - if (not_found) { + if (notFound) { return false; } return true; @@ -121,34 +140,34 @@ ListComponent.prototype = _.create(SharedComponent.prototype, { "constructor": L cls.match = function (token, context, editor) { if (!Array.isArray(token)) { - token = [token] + token = [token]; } - if (!this.allow_non_valid_values && !this.validateTokens(token, context, editor)) { - return null + if (!this.allowNonValidValues && !this.validateTokens(token, context, editor)) { + return null; } - var result = Object.getPrototypeOf(cls).match.call(this, token, context, editor); + const result = Object.getPrototypeOf(cls).match.call(this, token, context, editor); result.context_values = result.context_values || {}; result.context_values[this.getContextKey()] = token; return result; - } -})(ListComponent.prototype); + }; +}(ListComponent.prototype)); function SimpleParamComponent(name, parent) { SharedComponent.call(this, name, parent); } -SimpleParamComponent.prototype = _.create(SharedComponent.prototype, { "constructor": SimpleParamComponent }); +SimpleParamComponent.prototype = _.create(SharedComponent.prototype, { 'constructor': SimpleParamComponent }); (function (cls) { cls.match = function (token, context, editor) { - var result = Object.getPrototypeOf(cls).match.call(this, token, context, editor); + const result = Object.getPrototypeOf(cls).match.call(this, token, context, editor); result.context_values = result.context_values || {}; result.context_values[this.name] = token; return result; - } + }; -})(SimpleParamComponent.prototype); +}(SimpleParamComponent.prototype)); function ConstantComponent(name, parent, options) { SharedComponent.call(this, name, parent); @@ -158,7 +177,7 @@ function ConstantComponent(name, parent, options) { this.options = options || [name]; } -ConstantComponent.prototype = _.create(SharedComponent.prototype, { "constructor": ConstantComponent }); +ConstantComponent.prototype = _.create(SharedComponent.prototype, { 'constructor': ConstantComponent }); export { SharedComponent, ListComponent, SimpleParamComponent, ConstantComponent }; @@ -182,8 +201,8 @@ export { SharedComponent, ListComponent, SimpleParamComponent, ConstantComponent return Object.getPrototypeOf(cls).match.call(this, token, context, editor); - } -})(ConstantComponent.prototype); + }; +}(ConstantComponent.prototype)); export function wrapComponentWithDefaults(component, defaults) { function Wrapper() { @@ -191,14 +210,14 @@ export function wrapComponentWithDefaults(component, defaults) { } Wrapper.prototype = {}; - for (var key in component) { + for (const key in component) { if (_.isFunction(component[key])) { Wrapper.prototype[key] = _.bindKey(component, key); } } Wrapper.prototype.getTerms = function (context, editor) { - var result = component.getTerms(context, editor); + let result = component.getTerms(context, editor); if (!result) { return result; } @@ -213,7 +232,7 @@ export function wrapComponentWithDefaults(component, defaults) { return new Wrapper(); } -let tracer = function () { +const tracer = function () { if (window.engine_trace) { console.log.call(console, arguments); } @@ -226,7 +245,7 @@ function passThroughContext(context, extensionList) { } PTC.prototype = context; - var result = new PTC(); + const result = new PTC(); if (extensionList) { extensionList.unshift(result); _.assign.apply(_, extensionList); @@ -235,8 +254,8 @@ function passThroughContext(context, extensionList) { return result; } -function WalkingState(parent_name, components, contextExtensionList, depth, priority) { - this.parent_name = parent_name; +function WalkingState(parentName, components, contextExtensionList, depth, priority) { + this.parentName = parentName; this.components = components; this.contextExtensionList = contextExtensionList; this.depth = depth || 0; @@ -246,21 +265,22 @@ function WalkingState(parent_name, components, contextExtensionList, depth, prio function walkTokenPath(tokenPath, walkingStates, context, editor) { if (!tokenPath || tokenPath.length === 0) { - return walkingStates + return walkingStates; } - var token = tokenPath[0], - nextWalkingStates = []; + const token = tokenPath[0]; + const nextWalkingStates = []; - tracer("starting token evaluation [" + token + "]"); + tracer('starting token evaluation [' + token + ']'); _.each(walkingStates, function (ws) { - var contextForState = passThroughContext(context, ws.contextExtensionList); + const contextForState = passThroughContext(context, ws.contextExtensionList); _.each(ws.components, function (component) { - tracer("evaluating [" + token + "] with [" + component.name + "]", component); - var result = component.match(token, contextForState, editor); + tracer('evaluating [' + token + '] with [' + component.name + ']', component); + const result = component.match(token, contextForState, editor); if (result && !_.isEmpty(result)) { - tracer("matched [" + token + "] with:", result); - var next, extensionList; + tracer('matched [' + token + '] with:', result); + let next; + let extensionList; if (result.next && !Array.isArray(result.next)) { next = [result.next]; } @@ -276,7 +296,7 @@ function walkTokenPath(tokenPath, walkingStates, context, editor) { extensionList = ws.contextExtensionList; } - var priority = ws.priority; + let priority = ws.priority; if (_.isNumber(result.priority)) { if (_.isNumber(priority)) { priority = Math.min(priority, result.priority); @@ -291,29 +311,29 @@ function walkTokenPath(tokenPath, walkingStates, context, editor) { }); }); - if (nextWalkingStates.length == 0) { + if (nextWalkingStates.length === 0) { // no where to go, still return context variables returned so far.. return _.map(walkingStates, function (ws) { return new WalkingState(ws.name, [], ws.contextExtensionList); - }) + }); } return walkTokenPath(tokenPath.slice(1), nextWalkingStates, context, editor); } export function resolvePathToComponents(tokenPath, context, editor, components) { - var walkStates = walkTokenPath(tokenPath, [new WalkingState("ROOT", components, [])], context, editor); - var result = [].concat.apply([], _.pluck(walkStates, 'components')); + const walkStates = walkTokenPath(tokenPath, [new WalkingState('ROOT', components, [])], context, editor); + const result = [].concat.apply([], _.pluck(walkStates, 'components')); return result; } export function populateContext(tokenPath, context, editor, includeAutoComplete, components) { - var walkStates = walkTokenPath(tokenPath, [new WalkingState("ROOT", components, [])], context, editor); + let walkStates = walkTokenPath(tokenPath, [new WalkingState('ROOT', components, [])], context, editor); if (includeAutoComplete) { - var autoCompleteSet = []; + let autoCompleteSet = []; _.each(walkStates, function (ws) { - var contextForState = passThroughContext(context, ws.contextExtensionList); + const contextForState = passThroughContext(context, ws.contextExtensionList); _.each(ws.components, function (component) { _.each(component.getTerms(contextForState, editor), function (term) { if (!_.isObject(term)) { @@ -321,7 +341,7 @@ export function populateContext(tokenPath, context, editor, includeAutoComplete, } autoCompleteSet.push(term); }); - }) + }); }); autoCompleteSet = _.uniq(autoCompleteSet, false); context.autoCompleteSet = autoCompleteSet; @@ -329,16 +349,16 @@ export function populateContext(tokenPath, context, editor, includeAutoComplete, // apply what values were set so far to context, selecting the deepest on which sets the context if (walkStates.length !== 0) { - var wsToUse; + let wsToUse; walkStates = _.sortBy(walkStates, function (ws) { return _.isNumber(ws.priority) ? ws.priority : Number.MAX_VALUE; }); wsToUse = _.find(walkStates, function (ws) { - return _.isEmpty(ws.components) + return _.isEmpty(ws.components); }); if (!wsToUse && walkStates.length > 1 && !includeAutoComplete) { - console.info("more then one context active for current path, but autocomplete isn't requested", walkStates); + console.info('more then one context active for current path, but autocomplete isn\'t requested', walkStates); } if (!wsToUse) { diff --git a/src/core_plugins/console/public/src/autocomplete/url_params.js b/src/core_plugins/console/public/src/autocomplete/url_params.js index 0456921c97a05f..30edd380d98c13 100644 --- a/src/core_plugins/console/public/src/autocomplete/url_params.js +++ b/src/core_plugins/console/public/src/autocomplete/url_params.js @@ -1,47 +1,66 @@ -let _ = require('lodash'); -let engine = require('./engine'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const _ = require('lodash'); +const engine = require('./engine'); export function ParamComponent(name, parent, description) { engine.ConstantComponent.call(this, name, parent); this.description = description; } -ParamComponent.prototype = _.create(engine.ConstantComponent.prototype, { "constructor": ParamComponent }); +ParamComponent.prototype = _.create(engine.ConstantComponent.prototype, { 'constructor': ParamComponent }); (function (cls) { cls.getTerms = function () { - var t = { name: this.name }; - if (this.description === "__flag__") { - t.meta = "flag" + const t = { name: this.name }; + if (this.description === '__flag__') { + t.meta = 'flag'; } else { - t.meta = "param"; - t.insert_value = this.name + "="; + t.meta = 'param'; + t.insertValue = this.name + '='; } return [t]; }; -})(ParamComponent.prototype); +}(ParamComponent.prototype)); export function UrlParams(description, defaults) { // This is not really a component, just a handy container to make iteration logic simpler - this.rootComponent = new engine.SharedComponent("ROOT"); + this.rootComponent = new engine.SharedComponent('ROOT'); if (_.isUndefined(defaults)) { defaults = { - "pretty": "__flag__", - "format": ["json", "yaml"], - "filter_path": "", + 'pretty': '__flag__', + 'format': ['json', 'yaml'], + 'filter_path': '', }; } description = _.clone(description || {}); _.defaults(description, defaults); - _.each(description, function (p_description, param) { - var component = new ParamComponent(param, this.rootComponent, p_description); - if (Array.isArray(p_description)) { - new engine.ListComponent(param, p_description, component); + _.each(description, function (pDescription, param) { + const component = new ParamComponent(param, this.rootComponent, pDescription); + if (Array.isArray(pDescription)) { + new engine.ListComponent(param, pDescription, component); } - else if (p_description === "__flag__") { - new engine.ListComponent(param, ["true", "false"], component); + else if (pDescription === '__flag__') { + new engine.ListComponent(param, ['true', 'false'], component); } }, this); @@ -51,6 +70,6 @@ export function UrlParams(description, defaults) { cls.getTopLevelComponents = function () { return this.rootComponent.next; - } + }; -})(UrlParams.prototype); +}(UrlParams.prototype)); diff --git a/src/core_plugins/console/public/src/autocomplete/url_pattern_matcher.js b/src/core_plugins/console/public/src/autocomplete/url_pattern_matcher.js index acf8ecb8b241b7..82d8decf23b7d8 100644 --- a/src/core_plugins/console/public/src/autocomplete/url_pattern_matcher.js +++ b/src/core_plugins/console/public/src/autocomplete/url_pattern_matcher.js @@ -1,14 +1,33 @@ -let _ = require('lodash'); -let engine = require('./engine'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const _ = require('lodash'); +const engine = require('./engine'); -export const URL_PATH_END_MARKER = "__url_path_end__"; +export const URL_PATH_END_MARKER = '__url_path_end__'; function AcceptEndpointComponent(endpoint, parent) { engine.SharedComponent.call(this, endpoint.id, parent); - this.endpoint = endpoint + this.endpoint = endpoint; } -AcceptEndpointComponent.prototype = _.create(engine.SharedComponent.prototype, { "constructor": AcceptEndpointComponent }); +AcceptEndpointComponent.prototype = _.create(engine.SharedComponent.prototype, { 'constructor': AcceptEndpointComponent }); (function (cls) { @@ -19,15 +38,15 @@ AcceptEndpointComponent.prototype = _.create(engine.SharedComponent.prototype, { if (this.endpoint.methods && -1 === _.indexOf(this.endpoint.methods, context.method)) { return null; } - var r = Object.getPrototypeOf(cls).match.call(this, token, context, editor); + const r = Object.getPrototypeOf(cls).match.call(this, token, context, editor); r.context_values = r.context_values || {}; - r.context_values['endpoint'] = this.endpoint; + r.context_values.endpoint = this.endpoint; if (_.isNumber(this.endpoint.priority)) { r.priority = this.endpoint.priority; } return r; - } -})(AcceptEndpointComponent.prototype); + }; +}(AcceptEndpointComponent.prototype)); /** @@ -42,22 +61,22 @@ AcceptEndpointComponent.prototype = _.create(engine.SharedComponent.prototype, { */ export function UrlPatternMatcher(parametrizedComponentFactories) { // This is not really a component, just a handy container to make iteration logic simpler - this.rootComponent = new engine.SharedComponent("ROOT"); + this.rootComponent = new engine.SharedComponent('ROOT'); this.parametrizedComponentFactories = parametrizedComponentFactories || {}; } (function (cls) { cls.addEndpoint = function (pattern, endpoint) { - var c, - active_component = this.rootComponent, - endpointComponents = endpoint.url_components || {}; - var partList = pattern.split("/"); + let c; + let activeComponent = this.rootComponent; + const endpointComponents = endpoint.url_components || {}; + const partList = pattern.split('/'); _.each(partList, function (part, partIndex) { if (part.search(/^{.+}$/) >= 0) { part = part.substr(1, part.length - 2); - if (active_component.getComponent(part)) { + if (activeComponent.getComponent(part)) { // we already have something for this, reuse - active_component = active_component.getComponent(part); + activeComponent = activeComponent.getComponent(part); return; } // a new path, resolve. @@ -65,57 +84,58 @@ export function UrlPatternMatcher(parametrizedComponentFactories) { if ((c = endpointComponents[part])) { // endpoint specific. Support list if (Array.isArray(c)) { - c = new engine.ListComponent(part, c, active_component); + c = new engine.ListComponent(part, c, activeComponent); } - else if (_.isObject(c) && c.type === "list") { - c = new engine.ListComponent(part, c.list, active_component, c.multi_valued, c.allow_non_valid); + else if (_.isObject(c) && c.type === 'list') { + c = new engine.ListComponent(part, c.list, activeComponent, c.multiValued, c.allow_non_valid); } else { - console.warn("incorrectly configured url component ", part, " in endpoint", endpoint); + console.warn('incorrectly configured url component ', part, ' in endpoint', endpoint); c = new engine.SharedComponent(part); } } else if ((c = this.parametrizedComponentFactories[part])) { // c is a f - c = c(part, active_component); + c = c(part, activeComponent); } else { // just accept whatever with not suggestions - c = new engine.SimpleParamComponent(part, active_component); + c = new engine.SimpleParamComponent(part, activeComponent); } - active_component = c; + activeComponent = c; } else { // not pattern - var lookAhead = part, s; + let lookAhead = part; + let s; for (partIndex++; partIndex < partList.length; partIndex++) { s = partList[partIndex]; - if (s.indexOf("{") >= 0) { + if (s.indexOf('{') >= 0) { break; } - lookAhead += "/" + s; + lookAhead += '/' + s; } - if (active_component.getComponent(part)) { + if (activeComponent.getComponent(part)) { // we already have something for this, reuse - active_component = active_component.getComponent(part); - active_component.addOption(lookAhead); + activeComponent = activeComponent.getComponent(part); + activeComponent.addOption(lookAhead); } else { - c = new engine.ConstantComponent(part, active_component, lookAhead); - active_component = c; + c = new engine.ConstantComponent(part, activeComponent, lookAhead); + activeComponent = c; } } }, this); // mark end of endpoint path - new AcceptEndpointComponent(endpoint, active_component); + new AcceptEndpointComponent(endpoint, activeComponent); }; cls.getTopLevelComponents = function () { return this.rootComponent.next; - } + }; -})(UrlPatternMatcher.prototype); +}(UrlPatternMatcher.prototype)); diff --git a/src/core_plugins/console/public/src/controllers/sense_controller.js b/src/core_plugins/console/public/src/controllers/sense_controller.js index 76f3876f374ae5..228a508de2ca21 100644 --- a/src/core_plugins/console/public/src/controllers/sense_controller.js +++ b/src/core_plugins/console/public/src/controllers/sense_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import 'ui/doc_title'; import { useResizeChecker } from '../sense_editor_resize'; import $ from 'jquery'; @@ -21,7 +40,8 @@ module.controller('SenseController', function SenseController(Private, $scope, $ // We need to wait for these elements to be rendered before we can select them with jQuery // and then initialize this app - let input, output; + let input; + let output; $timeout(() => { output = initializeOutput($('#output')); input = initializeInput($('#editor'), $('#editor_actions'), $('#copy_as_curl'), output); diff --git a/src/core_plugins/console/public/src/controllers/sense_top_nav_controller.js b/src/core_plugins/console/public/src/controllers/sense_top_nav_controller.js index 9b522660c02cc1..967a0d9817171a 100644 --- a/src/core_plugins/console/public/src/controllers/sense_top_nav_controller.js +++ b/src/core_plugins/console/public/src/controllers/sense_top_nav_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { KbnTopNavControllerProvider } from 'ui/kbn_top_nav/kbn_top_nav_controller'; import storage from '../storage'; diff --git a/src/core_plugins/console/public/src/curl.js b/src/core_plugins/console/public/src/curl.js index 4bbd962dfc19a3..b1a4dd97bb231f 100644 --- a/src/core_plugins/console/public/src/curl.js +++ b/src/core_plugins/console/public/src/curl.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function detectCURLinLine(line) { // returns true if text matches a curl request return line.match(/^\s*?curl\s+(-X[A-Z]+)?\s*['"]?.*?['"]?(\s*$|\s+?-d\s*?['"])/); @@ -6,7 +25,7 @@ function detectCURLinLine(line) { export function detectCURL(text) { // returns true if text matches a curl request if (!text) return false; - for (var line of text.split("\n")) { + for (const line of text.split('\n')) { if (detectCURLinLine(line)) { return true; } @@ -15,28 +34,28 @@ export function detectCURL(text) { } export function parseCURL(text) { - var state = 'NONE'; - var out = []; - var body = []; - var line = ''; - var lines = text.trim().split("\n"); - var matches; - - var EmptyLine = /^\s*$/; - var Comment = /^\s*(?:#|\/{2,})(.*)\n?$/; - var ExecutionComment = /^\s*#!/; - var ClosingSingleQuote = /^([^']*)'/; - var ClosingDoubleQuote = /^((?:[^\\"]|\\.)*)"/; - var EscapedQuotes = /^((?:[^\\"']|\\.)+)/; - - var LooksLikeCurl = /^\s*curl\s+/; - var CurlVerb = /-X ?(GET|HEAD|POST|PUT|DELETE)/; - - var HasProtocol = /[\s"']https?:\/\//; - var CurlRequestWithProto = /[\s"']https?:\/\/[^\/ ]+\/+([^\s"']+)/; - var CurlRequestWithoutProto = /[\s"'][^\/ ]+\/+([^\s"']+)/; - var CurlData = /^.+\s(--data|-d)\s*/; - var SenseLine = /^\s*(GET|HEAD|POST|PUT|DELETE)\s+\/?(.+)/; + let state = 'NONE'; + const out = []; + let body = []; + let line = ''; + const lines = text.trim().split('\n'); + let matches; + + const EmptyLine = /^\s*$/; + const Comment = /^\s*(?:#|\/{2,})(.*)\n?$/; + const ExecutionComment = /^\s*#!/; + const ClosingSingleQuote = /^([^']*)'/; + const ClosingDoubleQuote = /^((?:[^\\"]|\\.)*)"/; + const EscapedQuotes = /^((?:[^\\"']|\\.)+)/; + + const LooksLikeCurl = /^\s*curl\s+/; + const CurlVerb = /-X ?(GET|HEAD|POST|PUT|DELETE)/; + + const HasProtocol = /[\s"']https?:\/\//; + const CurlRequestWithProto = /[\s"']https?:\/\/[^\/ ]+\/+([^\s"']+)/; + const CurlRequestWithoutProto = /[\s"'][^\/ ]+\/+([^\s"']+)/; + const CurlData = /^.+\s(--data|-d)\s*/; + const SenseLine = /^\s*(GET|HEAD|POST|PUT|DELETE)\s+\/?(.+)/; if (lines.length > 0 && ExecutionComment.test(lines[0])) { lines.shift(); @@ -46,26 +65,26 @@ export function parseCURL(text) { if (line.length > 0) { return true; } - if (lines.length == 0) { + if (lines.length === 0) { return false; } - line = lines.shift().replace(/[\r\n]+/g, "\n") + "\n"; + line = lines.shift().replace(/[\r\n]+/g, '\n') + '\n'; return true; } function unescapeLastBodyEl() { - var str = body.pop().replace(/\\([\\"'])/g, "$1"); + const str = body.pop().replace(/\\([\\"'])/g, '$1'); body.push(str); } // Is the next char a single or double quote? // If so remove it function detectQuote() { - if (line.substr(0, 1) == "'") { + if (line.substr(0, 1) === '\'') { line = line.substr(1); state = 'SINGLE_QUOTE'; } - else if (line.substr(0, 1) == '"') { + else if (line.substr(0, 1) === '"') { line = line.substr(1); state = 'DOUBLE_QUOTE'; } @@ -77,18 +96,18 @@ export function parseCURL(text) { // Body is finished - append to output with final LF function addBodyToOut() { if (body.length > 0) { - out.push(body.join("")); + out.push(body.join('')); body = []; } state = 'LF'; - out.push("\n"); + out.push('\n'); } // If the pattern matches, then the state is about to change, // so add the capture to the body and detect the next state // Otherwise add the whole line function consumeMatching(pattern) { - var matches = line.match(pattern); + const matches = line.match(pattern); if (matches) { body.push(matches[1]); line = line.substr(matches[0].length); @@ -101,16 +120,16 @@ export function parseCURL(text) { } function parseCurlLine() { - var verb = 'GET'; - var request = ''; - var matches; + let verb = 'GET'; + let request = ''; + let matches; if (matches = line.match(CurlVerb)) { verb = matches[1]; } // JS regexen don't support possesive quantifiers, so // we need two distinct patterns - var pattern = HasProtocol.test(line) + const pattern = HasProtocol.test(line) ? CurlRequestWithProto : CurlRequestWithoutProto; @@ -118,7 +137,7 @@ export function parseCURL(text) { request = matches[1]; } - out.push(verb + ' /' + request + "\n"); + out.push(verb + ' /' + request + '\n'); if (matches = line.match(CurlData)) { line = line.substr(matches[0].length); @@ -136,30 +155,30 @@ export function parseCURL(text) { while (nextLine()) { - if (state == 'SINGLE_QUOTE') { + if (state === 'SINGLE_QUOTE') { consumeMatching(ClosingSingleQuote); } - else if (state == 'DOUBLE_QUOTE') { + else if (state === 'DOUBLE_QUOTE') { consumeMatching(ClosingDoubleQuote); unescapeLastBodyEl(); } - else if (state == 'UNQUOTED') { + else if (state === 'UNQUOTED') { consumeMatching(EscapedQuotes); if (body.length) { unescapeLastBodyEl(); } - if (state == 'UNQUOTED') { + if (state === 'UNQUOTED') { addBodyToOut(); - line = '' + line = ''; } } // the BODY state (used to match the body of a Sense request) // can be terminated early if it encounters // a comment or an empty line - else if (state == 'BODY') { + else if (state === 'BODY') { if (Comment.test(line) || EmptyLine.test(line)) { addBodyToOut(); } @@ -170,15 +189,15 @@ export function parseCURL(text) { } else if (EmptyLine.test(line)) { - if (state != 'LF') { - out.push("\n"); + if (state !== 'LF') { + out.push('\n'); state = 'LF'; } line = ''; } else if (matches = line.match(Comment)) { - out.push("#" + matches[1] + "\n"); + out.push('#' + matches[1] + '\n'); state = 'NONE'; line = ''; } @@ -188,7 +207,7 @@ export function parseCURL(text) { } else if (matches = line.match(SenseLine)) { - out.push(matches[1] + ' /' + matches[2] + "\n"); + out.push(matches[1] + ' /' + matches[2] + '\n'); line = ''; state = 'BODY'; } diff --git a/src/core_plugins/console/public/src/directives/sense_help.js b/src/core_plugins/console/public/src/directives/sense_help.js index 62512f7abb20de..e244399e2d8338 100644 --- a/src/core_plugins/console/public/src/directives/sense_help.js +++ b/src/core_plugins/console/public/src/directives/sense_help.js @@ -1,10 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('./sense_help_example'); require('ui/modules') -.get('app/sense') -.directive('senseHelp', function () { - return { - restrict: 'E', - template: require('./help.html') - } -}); + .get('app/sense') + .directive('senseHelp', function () { + return { + restrict: 'E', + template: require('./help.html') + }; + }); diff --git a/src/core_plugins/console/public/src/directives/sense_help_example.js b/src/core_plugins/console/public/src/directives/sense_help_example.js index 6caf69fe6b98f3..6a7cbff4df3d79 100644 --- a/src/core_plugins/console/public/src/directives/sense_help_example.js +++ b/src/core_plugins/console/public/src/directives/sense_help_example.js @@ -1,22 +1,41 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const SenseEditor = require('../sense_editor/editor'); const exampleText = require('raw-loader!./helpExample.txt').trim(); import { useResizeChecker } from '../sense_editor_resize'; require('ui/modules') -.get('app/sense') -.directive('senseHelpExample', function () { - return { - restrict: 'E', - link: function ($scope, $el) { - $el.text(exampleText); - $scope.editor = new SenseEditor($el); - useResizeChecker($scope, $el, $scope.editor); - $scope.editor.setReadOnly(true); - $scope.editor.$blockScrolling = Infinity; + .get('app/sense') + .directive('senseHelpExample', function () { + return { + restrict: 'E', + link: function ($scope, $el) { + $el.text(exampleText); + $scope.editor = new SenseEditor($el); + useResizeChecker($scope, $el, $scope.editor); + $scope.editor.setReadOnly(true); + $scope.editor.$blockScrolling = Infinity; - $scope.$on('$destroy', function () { - if ($scope.editor) $scope.editor.destroy(); - }); - } - } -}) + $scope.$on('$destroy', function () { + if ($scope.editor) $scope.editor.destroy(); + }); + } + }; + }); diff --git a/src/core_plugins/console/public/src/directives/sense_history.js b/src/core_plugins/console/public/src/directives/sense_history.js index 66a57a81de606f..39e4bcf8e78356 100644 --- a/src/core_plugins/console/public/src/directives/sense_history.js +++ b/src/core_plugins/console/public/src/directives/sense_history.js @@ -1,67 +1,86 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { keyCodes } from '@elastic/eui'; -var { memoize } = require('lodash'); -let moment = require('moment'); +const { memoize } = require('lodash'); +const moment = require('moment'); -var history = require('../history'); +const history = require('../history'); require('./sense_history_viewer'); require('ui/modules') -.get('app/sense') -.directive('senseHistory', function () { - return { - restrict: 'E', - template: require('./history.html'), - controllerAs: 'history', - controller: function ($scope, $element) { - this.reqs = history.getHistory(); - this.selectedIndex = 0; - this.selectedReq = this.reqs[this.selectedIndex]; - this.viewingReq = this.selectedReq; + .get('app/sense') + .directive('senseHistory', function () { + return { + restrict: 'E', + template: require('./history.html'), + controllerAs: 'history', + controller: function ($scope, $element) { + this.reqs = history.getHistory(); + this.selectedIndex = 0; + this.selectedReq = this.reqs[this.selectedIndex]; + this.viewingReq = this.selectedReq; - // calculate the text description of a request - this.describeReq = memoize((req) => { - const endpoint = req.endpoint; - const date = moment(req.time); + // calculate the text description of a request + this.describeReq = memoize((req) => { + const endpoint = req.endpoint; + const date = moment(req.time); - let formattedDate = date.format("MMM D"); - if (date.diff(moment(), "days") > -7) { - formattedDate = date.fromNow(); - } + let formattedDate = date.format('MMM D'); + if (date.diff(moment(), 'days') > -7) { + formattedDate = date.fromNow(); + } - return `${endpoint} (${formattedDate})`; - }); - this.describeReq.cache = new WeakMap(); + return `${endpoint} (${formattedDate})`; + }); + this.describeReq.cache = new WeakMap(); - // main actions - this.clear = () => { - history.clearHistory($element); - $scope.kbnTopNav.close(); - }; + // main actions + this.clear = () => { + history.clearHistory($element); + $scope.kbnTopNav.close(); + }; - this.restore = (req = this.selectedReq) => { - history.restoreFromHistory(req); - $scope.kbnTopNav.close(); - }; + this.restore = (req = this.selectedReq) => { + history.restoreFromHistory(req); + $scope.kbnTopNav.close(); + }; - this.onKeyDown = (ev) => { - if (ev.keyCode === keyCodes.ENTER) { - this.restore(); - return; - } + this.onKeyDown = (ev) => { + if (ev.keyCode === keyCodes.ENTER) { + this.restore(); + return; + } - if (ev.keyCode === keyCodes.UP) { - ev.preventDefault(); - this.selectedIndex--; - } else if (ev.keyCode === keyCodes.DOWN) { - ev.preventDefault(); - this.selectedIndex++; - } + if (ev.keyCode === keyCodes.UP) { + ev.preventDefault(); + this.selectedIndex--; + } else if (ev.keyCode === keyCodes.DOWN) { + ev.preventDefault(); + this.selectedIndex++; + } - this.selectedIndex = Math.min(Math.max(0, this.selectedIndex), this.reqs.length - 1); - this.selectedReq = this.reqs[this.selectedIndex]; - this.viewingReq = this.reqs[this.selectedIndex]; - }; - } - }; -}); + this.selectedIndex = Math.min(Math.max(0, this.selectedIndex), this.reqs.length - 1); + this.selectedReq = this.reqs[this.selectedIndex]; + this.viewingReq = this.reqs[this.selectedIndex]; + }; + } + }; + }); diff --git a/src/core_plugins/console/public/src/directives/sense_history_viewer.js b/src/core_plugins/console/public/src/directives/sense_history_viewer.js index 91716e79f9f9b2..11f524fa2bf5ec 100644 --- a/src/core_plugins/console/public/src/directives/sense_history_viewer.js +++ b/src/core_plugins/console/public/src/directives/sense_history_viewer.js @@ -1,34 +1,54 @@ -let SenseEditor = require('../sense_editor/editor'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const SenseEditor = require('../sense_editor/editor'); + import { useResizeChecker } from '../sense_editor_resize'; require('ui/modules') -.get('app/sense') -.directive('senseHistoryViewer', function () { - return { - restrict: 'E', - scope: { - req: '=', - }, - link: function ($scope, $el) { - const viewer = new SenseEditor($el); - viewer.setReadOnly(true); - viewer.renderer.setShowPrintMargin(false); - useResizeChecker($scope, $el, viewer); - require('../settings').applyCurrentSettings(viewer); + .get('app/sense') + .directive('senseHistoryViewer', function () { + return { + restrict: 'E', + scope: { + req: '=', + }, + link: function ($scope, $el) { + const viewer = new SenseEditor($el); + viewer.setReadOnly(true); + viewer.renderer.setShowPrintMargin(false); + useResizeChecker($scope, $el, viewer); + require('../settings').applyCurrentSettings(viewer); - $scope.$watch('req', function (req) { - if (req) { - var s = req.method + " " + req.endpoint + "\n" + (req.data || ""); - viewer.setValue(s); - viewer.clearSelection(); - } else { - viewer.getSession().setValue("No history available") - } - }); + $scope.$watch('req', function (req) { + if (req) { + const s = req.method + ' ' + req.endpoint + '\n' + (req.data || ''); + viewer.setValue(s); + viewer.clearSelection(); + } else { + viewer.getSession().setValue('No history available'); + } + }); - $scope.$on('$destroy', function () { - viewer.destroy(); - }); - } - } -}) + $scope.$on('$destroy', function () { + viewer.destroy(); + }); + } + }; + }); diff --git a/src/core_plugins/console/public/src/directives/sense_settings.js b/src/core_plugins/console/public/src/directives/sense_settings.js index 72507467f8112d..d51b65fa966559 100644 --- a/src/core_plugins/console/public/src/directives/sense_settings.js +++ b/src/core_plugins/console/public/src/directives/sense_settings.js @@ -1,31 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('ui/directives/input_focus'); require('ui/modules') -.get('app/sense') -.directive('senseSettings', function () { - return { - restrict: 'E', - template: require('./settings.html'), - controllerAs: 'settings', - controller: function ($scope, $element) { - const settings = require('../settings'); + .get('app/sense') + .directive('senseSettings', function () { + return { + restrict: 'E', + template: require('./settings.html'), + controllerAs: 'settings', + controller: function ($scope, $element) { + const settings = require('../settings'); - this.vals = settings.getCurrentSettings(); - this.apply = () => { - this.vals = settings.updateSettings(this.vals); - $scope.kbnTopNav.close(); - }; + this.vals = settings.getCurrentSettings(); + this.apply = () => { + this.vals = settings.updateSettings(this.vals); + $scope.kbnTopNav.close(); + }; - const self = this; + const self = this; - function onEnter(event) { - if (event.which === 13) { - self.apply(); + function onEnter(event) { + if (event.which === 13) { + self.apply(); + } } - } - const boundElement = $element.bind('keydown', onEnter); - $scope.$on('$destroy', () => boundElement.unbind('keydown', onEnter)); - }, - }; -}); + const boundElement = $element.bind('keydown', onEnter); + $scope.$on('$destroy', () => boundElement.unbind('keydown', onEnter)); + }, + }; + }); diff --git a/src/core_plugins/console/public/src/directives/sense_welcome.js b/src/core_plugins/console/public/src/directives/sense_welcome.js index 28db076e6d7604..746cbd00e402d5 100644 --- a/src/core_plugins/console/public/src/directives/sense_welcome.js +++ b/src/core_plugins/console/public/src/directives/sense_welcome.js @@ -1,17 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('./sense_help_example'); const storage = require('../storage'); require('ui/modules') -.get('app/sense') -.directive('senseWelcome', function () { - return { - restrict: 'E', - template: require('./welcome.html'), - link: function ($scope) { - $scope.$on('$destroy', function () { - storage.set('version_welcome_shown', '@@SENSE_REVISION'); - }); - } - } -}); + .get('app/sense') + .directive('senseWelcome', function () { + return { + restrict: 'E', + template: require('./welcome.html'), + link: function ($scope) { + $scope.$on('$destroy', function () { + storage.set('version_welcome_shown', '@@SENSE_REVISION'); + }); + } + }; + }); diff --git a/src/core_plugins/console/public/src/es.js b/src/core_plugins/console/public/src/es.js index 6ba654188ae175..db5e153cec3d8f 100644 --- a/src/core_plugins/console/public/src/es.js +++ b/src/core_plugins/console/public/src/es.js @@ -1,7 +1,27 @@ -import { stringify as formatQueryString } from 'querystring' +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { stringify as formatQueryString } from 'querystring'; + import $ from 'jquery'; -let esVersion = []; +const esVersion = []; export function getVersion() { return esVersion; @@ -13,14 +33,14 @@ export function getContentType(body) { } export function send(method, path, data) { - var wrappedDfd = $.Deferred(); + const wrappedDfd = $.Deferred(); // eslint-disable-line new-cap - var isGetRequest = /^get$/i.test(method) + const isGetRequest = /^get$/i.test(method); if (data && isGetRequest) { - method = "POST"; + method = 'POST'; } - var options = { + const options = { url: '../api/console/proxy?' + formatQueryString({ path, method }), data, contentType: getContentType(data), @@ -36,8 +56,8 @@ export function send(method, path, data) { wrappedDfd.resolveWith(this, [data, textStatus, jqXHR]); }, function (jqXHR, textStatus, errorThrown) { - if (jqXHR.status == 0) { - jqXHR.responseText = "\n\nFailed to connect to Console's backend.\nPlease check the Kibana server is up and running"; + if (jqXHR.status === 0) { + jqXHR.responseText = '\n\nFailed to connect to Console\'s backend.\nPlease check the Kibana server is up and running'; } wrappedDfd.rejectWith(this, [jqXHR, textStatus, errorThrown]); }); diff --git a/src/core_plugins/console/public/src/history.js b/src/core_plugins/console/public/src/history.js index 935808374cb4d2..14d6ef5fcff04b 100644 --- a/src/core_plugins/console/public/src/history.js +++ b/src/core_plugins/console/public/src/history.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const $ = require('jquery'); const storage = require('./storage'); @@ -23,14 +42,14 @@ const history = { }, addToHistory(endpoint, method, data) { - var keys = history.getHistoryKeys(); + const keys = history.getHistoryKeys(); keys.splice(0, 500); // only maintain most recent X; $.each(keys, function (i, k) { storage.delete(k); }); - var timestamp = new Date().getTime(); - var k = "hist_elem_" + timestamp; + const timestamp = new Date().getTime(); + const k = 'hist_elem_' + timestamp; storage.set(k, { time: timestamp, endpoint: endpoint, @@ -40,8 +59,8 @@ const history = { }, updateCurrentState(content) { - var timestamp = new Date().getTime(); - storage.set("editor_state", { + const timestamp = new Date().getTime(); + storage.set('editor_state', { time: timestamp, content: content }); diff --git a/src/core_plugins/console/public/src/input.js b/src/core_plugins/console/public/src/input.js index 441879fea27f87..e75447db4bd042 100644 --- a/src/core_plugins/console/public/src/input.js +++ b/src/core_plugins/console/public/src/input.js @@ -1,12 +1,31 @@ -let $ = require('jquery'); +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const $ = require('jquery'); require('ace'); -require('ace/ext-searchbox'); -let Autocomplete = require('./autocomplete'); -let SenseEditor = require('./sense_editor/editor'); -let settings = require('./settings'); -let utils = require('./utils'); -let es = require('./es'); -let history = require('./history'); +require('brace/ext/searchbox'); +const Autocomplete = require('./autocomplete'); +const SenseEditor = require('./sense_editor/editor'); +const settings = require('./settings'); +const utils = require('./utils'); +const es = require('./es'); +const history = require('./history'); import { uiModules } from 'ui/modules'; let input; @@ -14,7 +33,7 @@ export function initializeInput($el, $actionsEl, $copyAsCurlEl, output) { input = new SenseEditor($el); // this may not exist if running from tests - let appSense = uiModules.get('app/sense'); + const appSense = uiModules.get('app/sense'); appSense.setupResizeCheckerForRootEditors($el, input, output); input.autocomplete = new Autocomplete(input); @@ -32,14 +51,14 @@ export function initializeInput($el, $actionsEl, $copyAsCurlEl, output) { name: 'move to previous request start or end', bindKey: { win: 'Ctrl-Up', mac: 'Command-Up' }, exec: function () { - input.moveToPreviousRequestEdge() + input.moveToPreviousRequestEdge(); } }); input.commands.addCommand({ name: 'move to next request start or end', bindKey: { win: 'Ctrl-Down', mac: 'Command-Down' }, exec: function () { - input.moveToNextRequestEdge() + input.moveToNextRequestEdge(); } }); @@ -48,78 +67,78 @@ export function initializeInput($el, $actionsEl, $copyAsCurlEl, output) { * COPY AS CURL */ (function setupClipboard() { - function copyText(text) { - var node = $(` - - - -

- Invalid JSON syntax -

- - - - - - - - - -

- Image is too large, maximum size is {{conf.options.maxSize.description}} -

- - - - - - - {{conf.value || conf.defVal}} - - - {{(conf.value || conf.defVal).join(', ')}} - - - {{conf.value === undefined ? conf.defVal : conf.value}} - - - Image - - - - - - -
-
- - - - - - - - - - - -
-
- - diff --git a/src/core_plugins/kibana/public/management/sections/settings/advanced_row.js b/src/core_plugins/kibana/public/management/sections/settings/advanced_row.js deleted file mode 100644 index 6f3b4b07cacb27..00000000000000 --- a/src/core_plugins/kibana/public/management/sections/settings/advanced_row.js +++ /dev/null @@ -1,81 +0,0 @@ -import 'ui/elastic_textarea'; -import 'ui/filters/markdown'; -import { uiModules } from 'ui/modules'; -import { fatalError } from 'ui/notify'; -import { keyCodes } from '@elastic/eui'; -import advancedRowTemplate from './advanced_row.html'; - -uiModules.get('apps/management') - .directive('advancedRow', function (config) { - return { - restrict: 'A', - replace: true, - template: advancedRowTemplate, - scope: { - conf: '=advancedRow', - configs: '=' - }, - link: function ($scope) { - // To allow passing form validation state back - $scope.forms = {}; - - // setup loading flag, run async op, then clear loading and editing flag (just in case) - const loading = function (conf, fn) { - conf.loading = true; - fn() - .then(function () { - conf.loading = conf.editing = false; - }) - .catch(fatalError); - }; - - $scope.maybeCancel = function ($event, conf) { - if ($event.keyCode === keyCodes.ESCAPE) { - $scope.cancelEdit(conf); - } - }; - - $scope.edit = function (conf) { - conf.unsavedValue = conf.value == null ? conf.defVal : conf.value; - $scope.configs.forEach(function (c) { - c.editing = (c === conf); - }); - }; - - $scope.save = function (conf) { - // an empty JSON is valid as per the validateJson directive. - // set the value to empty JSON in this case so that its parsing upon retrieving the setting does not fail. - if (conf.type === 'json' && conf.unsavedValue === '') { - conf.unsavedValue = '{}'; - } - - loading(conf, function () { - if (conf.unsavedValue === conf.defVal) { - return config.remove(conf.name); - } - - return config.set(conf.name, conf.unsavedValue); - }); - }; - - $scope.cancelEdit = function (conf) { - conf.editing = false; - }; - - $scope.clear = function (conf) { - return loading(conf, function () { - return config.remove(conf.name); - }); - }; - - $scope.isDefaultValue = (conf) => { - // conf.isCustom = custom setting, provided by user, so there is no notion of - // having a default or non-default value for it - return conf.isCustom - || conf.value === undefined - || conf.value === '' - || String(conf.value) === String(conf.defVal); - }; - } - }; - }); diff --git a/src/core_plugins/kibana/public/management/sections/settings/advanced_settings.js b/src/core_plugins/kibana/public/management/sections/settings/advanced_settings.js new file mode 100644 index 00000000000000..a826446e2cddea --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/advanced_settings.js @@ -0,0 +1,165 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; + +import { + Comparators, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, + Query, +} from '@elastic/eui'; + +import { CallOuts } from './components/call_outs'; +import { Search } from './components/search'; +import { Form } from './components/form'; + +import { getAriaName, toEditableConfig, DEFAULT_CATEGORY } from './lib'; + +import './advanced_settings.less'; + +export class AdvancedSettings extends Component { + static propTypes = { + config: PropTypes.object.isRequired, + query: PropTypes.string, + } + + constructor(props) { + super(props); + const { config, query } = this.props; + const parsedQuery = Query.parse(query ? `ariaName:"${getAriaName(query)}"` : ''); + this.init(config); + this.state = { + query: parsedQuery, + filteredSettings: this.mapSettings(Query.execute(parsedQuery, this.settings)), + }; + } + + init(config) { + this.settings = this.mapConfig(config); + this.groupedSettings = this.mapSettings(this.settings); + + this.categories = Object.keys(this.groupedSettings).sort((a, b) => { + if(a === DEFAULT_CATEGORY) return -1; + if(b === DEFAULT_CATEGORY) return 1; + if(a > b) return 1; + return a === b ? 0 : -1; + }); + + this.categoryCounts = Object.keys(this.groupedSettings).reduce((counts, category) => { + counts[category] = this.groupedSettings[category].length; + return counts; + }, {}); + } + + componentWillReceiveProps(nextProps) { + const { config } = nextProps; + const { query } = this.state; + + this.init(config); + this.setState({ + filteredSettings: this.mapSettings(Query.execute(query, this.settings)), + }); + } + + mapConfig(config) { + const all = config.getAll(); + return Object.entries(all) + .map((setting) => { + return toEditableConfig({ + def: setting[1], + name: setting[0], + value: setting[1].userValue, + isCustom: config.isCustom(setting[0]), + }); + }) + .filter((c) => !c.readonly) + .sort(Comparators.property('name', Comparators.default('asc'))); + } + + mapSettings(settings) { + // Group settings by category + return settings.reduce((groupedSettings, setting) => { + // We will want to change this logic when we put each category on its + // own page aka allowing a setting to be included in multiple categories. + const category = setting.category[0]; + (groupedSettings[category] = groupedSettings[category] || []).push(setting); + return groupedSettings; + }, {}); + } + + saveConfig = (name, value) => { + return this.props.config.set(name, value); + } + + clearConfig = (name) => { + return this.props.config.remove(name); + } + + onQueryChange = (query) => { + this.setState({ + query, + filteredSettings: this.mapSettings(Query.execute(query, this.settings)), + }); + } + + clearQuery = () => { + this.setState({ + query: Query.parse(''), + filteredSettings: this.groupedSettings, + }); + } + + render() { + const { filteredSettings, query } = this.state; + + return ( +
+ + + +

Settings

+
+
+ + + +
+ + + +
+
+ ); + } +} diff --git a/src/core_plugins/kibana/public/management/sections/settings/advanced_settings.less b/src/core_plugins/kibana/public/management/sections/settings/advanced_settings.less new file mode 100644 index 00000000000000..5201e5781595ad --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/advanced_settings.less @@ -0,0 +1,30 @@ +@import (reference) '~ui/styles/variables/colors'; + +.advancedSettings { + padding: 20px; + background: @globalColorLightestGray; + min-height: calc(~"100vh - 70px"); + + > div { + max-width: 1000px; + margin: 0 auto; + } + + .advancedSettings__field { + + * { + margin-top: 24px; + } + + &__wrapper { + width: 720px; + } + + &__actions { + padding-top: 30px; + } + + .euiFormHelpText { + padding-bottom: 0; + } + } +} diff --git a/src/core_plugins/kibana/public/management/sections/settings/advanced_settings.test.js b/src/core_plugins/kibana/public/management/sections/settings/advanced_settings.test.js new file mode 100644 index 00000000000000..113f23b6b6f4a5 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/advanced_settings.test.js @@ -0,0 +1,138 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; + +import { AdvancedSettings } from './advanced_settings'; + +jest.mock('./components/field', () => ({ + Field: () => { + return 'field'; + } +})); + +jest.mock('./components/call_outs', () => ({ + CallOuts: () => { + return 'callOuts'; + } +})); + +jest.mock('./components/search', () => ({ + Search: () => { + return 'search'; + } +})); + +const config = { + set: () => {}, + remove: () => {}, + isCustom: (setting) => setting.isCustom, + getAll: () => { + return { + 'test:array:setting': { + value: ['default_value'], + name: 'Test array setting', + description: 'Description for Test array setting', + category: ['elasticsearch'], + }, + 'test:boolean:setting': { + value: true, + name: 'Test boolean setting', + description: 'Description for Test boolean setting', + category: ['elasticsearch'], + }, + 'test:image:setting': { + value: null, + name: 'Test image setting', + description: 'Description for Test image setting', + type: 'image', + }, + 'test:json:setting': { + value: '{"foo": "bar"}', + name: 'Test json setting', + description: 'Description for Test json setting', + type: 'json', + }, + 'test:markdown:setting': { + value: '', + name: 'Test markdown setting', + description: 'Description for Test markdown setting', + type: 'markdown', + }, + 'test:number:setting': { + value: 5, + name: 'Test number setting', + description: 'Description for Test number setting', + }, + 'test:select:setting': { + value: 'orange', + name: 'Test select setting', + description: 'Description for Test select setting', + type: 'select', + options: ['apple', 'orange', 'banana'], + }, + 'test:string:setting': { + value: null, + name: 'Test string setting', + description: 'Description for Test string setting', + type: 'string', + isCustom: true, + }, + 'test:readonlystring:setting': { + value: null, + name: 'Test readonly string setting', + description: 'Description for Test readonly string setting', + type: 'string', + readonly: true, + }, + 'test:customstring:setting': { + value: null, + name: 'Test custom string setting', + description: 'Description for Test custom string setting', + type: 'string', + isCustom: true, + }, + }; + } +}; + +describe('AdvancedSettings', () => { + + it('should render normally', async () => { + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render specific setting if given setting key', async () => { + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/__snapshots__/call_outs.test.js.snap b/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/__snapshots__/call_outs.test.js.snap new file mode 100644 index 00000000000000..07d2370841f96a --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/__snapshots__/call_outs.test.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CallOuts should render normally 1`] = ` +
+ +

+ Be careful in here, these settings are for very advanced users only. Tweaks you make here can break large portions of Kibana. Some of these settings may be undocumented, unsupported or experimental. If a field has a default value, blanking the field will reset it to its default which may be unacceptable given other configuration directives. Deleting a custom setting will permanently remove it from Kibana's config. +

+
+
+`; diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.js b/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.js new file mode 100644 index 00000000000000..db9735d12fff64 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.js @@ -0,0 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; + +import { + EuiCallOut, +} from '@elastic/eui'; + +export const CallOuts = () => { + return ( +
+ +

+ Be careful in here, these settings are for very advanced users only. + Tweaks you make here can break large portions of Kibana. + Some of these settings may be undocumented, unsupported or experimental. + If a field has a default value, blanking the field will reset it to its default which may be + unacceptable given other configuration directives. + Deleting a custom setting will permanently remove it from Kibana's config. +

+
+
+ ); +}; diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.test.js b/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.test.js new file mode 100644 index 00000000000000..4add85d1206ab4 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/call_outs.test.js @@ -0,0 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; + +import { CallOuts } from './call_outs'; + +describe('CallOuts', () => { + it('should render normally', async () => { + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/index.js b/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/index.js new file mode 100644 index 00000000000000..7eba0da3689abe --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/call_outs/index.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { CallOuts } from './call_outs'; diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap b/src/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap new file mode 100644 index 00000000000000..ea478bac32a953 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap @@ -0,0 +1,2315 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Field for array setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="array:test:setting-aria" + title={ +

+ Array test setting + +

+ } + titleSize="xs" + > + + array:test:setting + + } + > + + + + + + +`; + +exports[`Field for array setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="array:test:setting-aria" + title={ +

+ Array test setting + +

+ } + titleSize="xs" + > + + array:test:setting + + } + > + + + + + + +`; + +exports[`Field for array setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + Default: + + default_value + + + + + } + fullWidth={false} + gutterSize="l" + idAria="array:test:setting-aria" + title={ +

+ Array test setting + +

+ } + titleSize="xs" + > + + + + Reset to default + +     + + + } + isInvalid={false} + label={ + + array:test:setting + + } + > + + + + + + +`; + +exports[`Field for boolean setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="boolean:test:setting-aria" + title={ +

+ Boolean test setting + +

+ } + titleSize="xs" + > + + boolean:test:setting + + } + > + + + + + + +`; + +exports[`Field for boolean setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="boolean:test:setting-aria" + title={ +

+ Boolean test setting + +

+ } + titleSize="xs" + > + + boolean:test:setting + + } + > + + + + + + +`; + +exports[`Field for boolean setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + Default: + + true + + + + + } + fullWidth={false} + gutterSize="l" + idAria="boolean:test:setting-aria" + title={ +

+ Boolean test setting + +

+ } + titleSize="xs" + > + + + + Reset to default + +     + + + } + isInvalid={false} + label={ + + boolean:test:setting + + } + > + + + + + + +`; + +exports[`Field for image setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="image:test:setting-aria" + title={ +

+ Image test setting + +

+ } + titleSize="xs" + > + + image:test:setting + + } + > + + + + + + +`; + +exports[`Field for image setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="image:test:setting-aria" + title={ +

+ Image test setting + +

+ } + titleSize="xs" + > + + image:test:setting + + } + > + + + + + + +`; + +exports[`Field for image setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + Default: + + null + + + + + } + fullWidth={false} + gutterSize="l" + idAria="image:test:setting-aria" + title={ +

+ Image test setting + +

+ } + titleSize="xs" + > + + + + Reset to default + +     + + + + Change image + + + + } + isInvalid={false} + label={ + + image:test:setting + + } + > + + + + + + +`; + +exports[`Field for json setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="json:test:setting-aria" + title={ +

+ Json test setting + +

+ } + titleSize="xs" + > + + json:test:setting + + } + > +
+ +
+
+ + + + +`; + +exports[`Field for json setting should render default value if there is no user value set 1`] = ` + + + +
+ + + + Default: + + {} + + + + + } + fullWidth={false} + gutterSize="l" + idAria="json:test:setting-aria" + title={ +

+ Json test setting + +

+ } + titleSize="xs" + > + + + + Reset to default + +     + + + } + isInvalid={false} + label={ + + json:test:setting + + } + > +
+ +
+
+ + + + +`; + +exports[`Field for json setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + Default: + + {} + + + + + } + fullWidth={false} + gutterSize="l" + idAria="json:test:setting-aria" + title={ +

+ Json test setting + +

+ } + titleSize="xs" + > + + + + Reset to default + +     + + + } + isInvalid={false} + label={ + + json:test:setting + + } + > +
+ +
+
+ + + + +`; + +exports[`Field for markdown setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="markdown:test:setting-aria" + title={ +

+ Markdown test setting + +

+ } + titleSize="xs" + > + + markdown:test:setting + + } + > +
+ +
+
+ + + + +`; + +exports[`Field for markdown setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="markdown:test:setting-aria" + title={ +

+ Markdown test setting + +

+ } + titleSize="xs" + > + + markdown:test:setting + + } + > +
+ +
+
+ + + + +`; + +exports[`Field for markdown setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + Default: + + null + + + + + } + fullWidth={false} + gutterSize="l" + idAria="markdown:test:setting-aria" + title={ +

+ Markdown test setting + +

+ } + titleSize="xs" + > + + + + Reset to default + +     + + + } + isInvalid={false} + label={ + + markdown:test:setting + + } + > +
+ +
+
+ + + + +`; + +exports[`Field for number setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="number:test:setting-aria" + title={ +

+ Number test setting + +

+ } + titleSize="xs" + > + + number:test:setting + + } + > + + + + + + +`; + +exports[`Field for number setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="number:test:setting-aria" + title={ +

+ Number test setting + +

+ } + titleSize="xs" + > + + number:test:setting + + } + > + + + + + + +`; + +exports[`Field for number setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + Default: + + 5 + + + + + } + fullWidth={false} + gutterSize="l" + idAria="number:test:setting-aria" + title={ +

+ Number test setting + +

+ } + titleSize="xs" + > + + + + Reset to default + +     + + + } + isInvalid={false} + label={ + + number:test:setting + + } + > + + + + + + +`; + +exports[`Field for select setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="select:test:setting-aria" + title={ +

+ Select test setting + +

+ } + titleSize="xs" + > + + select:test:setting + + } + > + + + + + + +`; + +exports[`Field for select setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="select:test:setting-aria" + title={ +

+ Select test setting + +

+ } + titleSize="xs" + > + + select:test:setting + + } + > + + + + + + +`; + +exports[`Field for select setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + Default: + + orange + + + + + } + fullWidth={false} + gutterSize="l" + idAria="select:test:setting-aria" + title={ +

+ Select test setting + +

+ } + titleSize="xs" + > + + + + Reset to default + +     + + + } + isInvalid={false} + label={ + + select:test:setting + + } + > + + + + + + +`; + +exports[`Field for string setting should render custom setting icon if it is custom 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="string:test:setting-aria" + title={ +

+ String test setting + +

+ } + titleSize="xs" + > + + string:test:setting + + } + > + + + + + + +`; + +exports[`Field for string setting should render default value if there is no user value set 1`] = ` + + + +
+ + } + fullWidth={false} + gutterSize="l" + idAria="string:test:setting-aria" + title={ +

+ String test setting + +

+ } + titleSize="xs" + > + + string:test:setting + + } + > + + + + + + +`; + +exports[`Field for string setting should render user value if there is user value is set 1`] = ` + + + +
+ + + + Default: + + null + + + + + } + fullWidth={false} + gutterSize="l" + idAria="string:test:setting-aria" + title={ +

+ String test setting + +

+ } + titleSize="xs" + > + + + + Reset to default + +     + + + } + isInvalid={false} + label={ + + string:test:setting + + } + > + + + + + + +`; diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/field/field.js b/src/core_plugins/kibana/public/management/sections/settings/components/field/field.js new file mode 100644 index 00000000000000..7336a4fa0d509d --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/field/field.js @@ -0,0 +1,587 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { PureComponent, Fragment } from 'react'; +import PropTypes from 'prop-types'; + +import 'brace/theme/textmate'; +import 'brace/mode/markdown'; + +import { toastNotifications } from 'ui/notify'; +import { + EuiButton, + EuiButtonEmpty, + EuiCode, + EuiCodeEditor, + EuiDescribedFormGroup, + EuiFieldNumber, + EuiFieldText, + EuiFilePicker, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiIconTip, + EuiImage, + EuiLink, + EuiSpacer, + EuiText, + EuiSelect, + EuiSwitch, + keyCodes, +} from '@elastic/eui'; + +import { isDefaultValue } from '../../lib'; + +export class Field extends PureComponent { + + static propTypes = { + setting: PropTypes.object.isRequired, + save: PropTypes.func.isRequired, + clear: PropTypes.func.isRequired, + } + + constructor(props) { + super(props); + const { type, value, defVal } = this.props.setting; + const editableValue = this.getEditableValue(type, value, defVal); + + this.state = { + isInvalid: false, + error: null, + loading: false, + changeImage: false, + savedValue: editableValue, + unsavedValue: editableValue, + isJsonArray: type === 'json' ? Array.isArray(JSON.parse(defVal || '{}')) : false, + }; + this.changeImageForm = null; + } + + componentWillReceiveProps(nextProps) { + const { unsavedValue } = this.state; + const { type, value, defVal } = nextProps.setting; + const editableValue = this.getEditableValue(type, value, defVal); + + this.setState({ + savedValue: editableValue, + unsavedValue: (value === null || value === undefined) ? editableValue : unsavedValue, + }); + } + + getEditableValue(type, value, defVal) { + const val = (value === null || value === undefined) ? defVal : value; + switch(type) { + case 'array': + return val.join(', '); + case 'boolean': + return !!val; + case 'number': + return Number(val); + case 'image': + return val; + default: + return val || ''; + } + } + + getDisplayedDefaultValue(type, defVal) { + if(defVal === undefined || defVal === null || defVal === '') { + return 'null'; + } + switch(type) { + case 'array': + return defVal.join(', '); + default: + return String(defVal); + } + } + + setLoading(loading) { + this.setState({ + loading + }); + } + + clearError() { + this.setState({ + isInvalid: false, + error: null, + }); + } + + onCodeEditorChange = (value) => { + const { type } = this.props.setting; + const { isJsonArray } = this.state; + + let newUnsavedValue = undefined; + let isInvalid = false; + let error = null; + + switch (type) { + case 'json': + newUnsavedValue = value.trim() || (isJsonArray ? '[]' : '{}'); + try { + JSON.parse(newUnsavedValue); + } catch (e) { + isInvalid = true; + error = 'Invalid JSON syntax'; + } + break; + default: + newUnsavedValue = value; + } + + this.setState({ + error, + isInvalid, + unsavedValue: newUnsavedValue, + }); + } + + onFieldChange = (e) => { + const value = e.target.value; + const { type } = this.props.setting; + const { unsavedValue } = this.state; + + let newUnsavedValue = undefined; + + switch (type) { + case 'boolean': + newUnsavedValue = !unsavedValue; + break; + case 'number': + newUnsavedValue = Number(value); + break; + default: + newUnsavedValue = value; + } + this.setState({ + unsavedValue: newUnsavedValue, + }); + } + + onFieldKeyDown = ({ keyCode }) => { + if (keyCode === keyCodes.ENTER) { + this.saveEdit(); + } + if (keyCode === keyCodes.ESCAPE) { + this.cancelEdit(); + } + } + + onFieldEscape = ({ keyCode }) => { + if (keyCode === keyCodes.ESCAPE) { + this.cancelEdit(); + } + } + + onImageChange = async (files) => { + if(!files.length) { + this.clearError(); + this.setState({ + unsavedValue: null, + }); + return; + } + + const file = files[0]; + const { maxSize } = this.props.setting.options; + try { + const base64Image = await this.getImageAsBase64(file); + const isInvalid = !!(maxSize && maxSize.length && base64Image.length > maxSize.length); + this.setState({ + isInvalid, + error: isInvalid ? `Image is too large, maximum size is ${maxSize.description}` : null, + changeImage: true, + unsavedValue: base64Image, + }); + } catch(err) { + toastNotifications.addDanger('Image could not be saved'); + this.cancelChangeImage(); + } + } + + getImageAsBase64(file) { + if(!file instanceof File) { + return null; + } + + const reader = new FileReader(); + reader.readAsDataURL(file); + + return new Promise((resolve, reject) => { + reader.onload = () => { + resolve(reader.result); + }; + reader.onerror = (err) => { + reject(err); + }; + }); + } + + changeImage = () => { + this.setState({ + changeImage: true, + }); + } + + cancelChangeImage = () => { + const { savedValue } = this.state; + + if(this.changeImageForm) { + this.changeImageForm.fileInput.value = null; + this.changeImageForm.handleChange(); + } + + this.setState({ + changeImage: false, + unsavedValue: savedValue, + }); + } + + cancelEdit = () => { + const { savedValue } = this.state; + this.clearError(); + this.setState({ + unsavedValue: savedValue, + }); + } + + saveEdit = async () => { + const { name, defVal, type } = this.props.setting; + const { changeImage, savedValue, unsavedValue, isJsonArray } = this.state; + + if(savedValue === unsavedValue) { + return; + } + + let valueToSave = unsavedValue; + let isSameValue = false; + + switch(type) { + case 'array': + valueToSave = valueToSave.split(',').map(val => val.trim()); + isSameValue = valueToSave.join(',') === defVal.join(','); + break; + case 'json': + valueToSave = valueToSave.trim(); + valueToSave = valueToSave || (isJsonArray ? '[]' : '{}'); + default: + isSameValue = valueToSave === defVal; + } + + this.setLoading(true); + try { + if (isSameValue) { + await this.props.clear(name); + } else { + await this.props.save(name, valueToSave); + } + + if(changeImage) { + this.cancelChangeImage(); + } + } catch(e) { + toastNotifications.addDanger(`Unable to save ${name}`); + } + this.setLoading(false); + } + + resetField = async () => { + const { name } = this.props.setting; + this.setLoading(true); + try { + await this.props.clear(name); + this.cancelChangeImage(); + this.clearError(); + } catch(e) { + toastNotifications.addDanger(`Unable to reset ${name}`); + } + this.setLoading(false); + } + + renderField(setting) { + const { loading, changeImage, unsavedValue } = this.state; + const { name, value, type, options } = setting; + + switch(type) { + case 'boolean': + return ( + + ); + case 'markdown': + case 'json': + return ( +
+ +
+ ); + case 'image': + if(!isDefaultValue(setting) && !changeImage) { + return ( + + ); + } else { + return ( + { this.changeImageForm = input; }} + onKeyDown={this.onFieldEscape} + data-test-subj={`advancedSetting-editField-${name}`} + /> + ); + } + case 'select': + return ( + { + return { text, value: text }; + })} + onChange={this.onFieldChange} + isLoading={loading} + disabled={loading} + onKeyDown={this.onFieldKeyDown} + data-test-subj={`advancedSetting-editField-${name}`} + /> + ); + case 'number': + return ( + + ); + default: + return ( + + ); + } + } + + renderLabel(setting) { + return( + + {setting.name} + + ); + } + + renderHelpText(setting) { + const defaultLink = this.renderResetToDefaultLink(setting); + const imageLink = this.renderChangeImageLink(setting); + + if(defaultLink || imageLink) { + return ( + + {defaultLink} + {imageLink} + + ); + } + + return null; + } + + renderTitle(setting) { + return ( +

+ {setting.displayName || setting.name} + {setting.isCustom ? + + : ''} +

+ ); + } + + renderDescription(setting) { + return ( + +
+ {this.renderDefaultValue(setting)} + + ); + } + + renderDefaultValue(setting) { + const { type, defVal } = setting; + if(isDefaultValue(setting)) { + return; + } + return ( + + + + Default: {this.getDisplayedDefaultValue(type, defVal)} + + + ); + } + + renderResetToDefaultLink(setting) { + const { ariaName, name } = setting; + if(isDefaultValue(setting)) { + return; + } + return ( + + + Reset to default + +     + + ); + } + + renderChangeImageLink(setting) { + const { changeImage } = this.state; + const { type, value, ariaName, name } = setting; + if(type !== 'image' || !value || changeImage) { + return; + } + return ( + + + Change image + + + ); + } + + renderActions(setting) { + const { ariaName, name } = setting; + const { loading, isInvalid, changeImage, savedValue, unsavedValue } = this.state; + if(savedValue === unsavedValue && !changeImage) { + return; + } + return ( + + + + + Save + + + + changeImage ? this.cancelChangeImage() : this.cancelEdit()} + disabled={loading} + data-test-subj={`advancedSetting-cancelEditField-${name}`} + > + Cancel + + + + + ); + } + + render() { + const { setting } = this.props; + const { error, isInvalid } = this.state; + + return ( + + + + + {this.renderField(setting)} + + + + + {this.renderActions(setting)} + + + ); + } +} diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/field/field.test.js b/src/core_plugins/kibana/public/management/sections/settings/components/field/field.test.js new file mode 100644 index 00000000000000..f49fc88b0e5cb2 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/field/field.test.js @@ -0,0 +1,331 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { mount, shallow } from 'enzyme'; + +import { findTestSubject } from '@elastic/eui/lib/test'; +import { Field } from './field'; + +jest.mock('ui/notify', () => ({ + toastNotifications: { + addDanger: () => {} + } +})); + +jest.mock('brace/theme/textmate', () => 'brace/theme/textmate'); +jest.mock('brace/mode/markdown', () => 'brace/mode/markdown'); + +const settings = { + array: { + name: 'array:test:setting', + ariaName: 'array test setting', + displayName: 'Array test setting', + description: 'Description for Array test setting', + type: 'array', + value: undefined, + defVal: ['default_value'], + isCustom: false, + options: null, + }, + boolean: { + name: 'boolean:test:setting', + ariaName: 'boolean test setting', + displayName: 'Boolean test setting', + description: 'Description for Boolean test setting', + type: 'boolean', + value: undefined, + defVal: true, + isCustom: false, + options: null, + }, + image: { + name: 'image:test:setting', + ariaName: 'image test setting', + displayName: 'Image test setting', + description: 'Description for Image test setting', + type: 'image', + value: undefined, + defVal: null, + isCustom: false, + options: { + maxSize: { + length: 1000, + displayName: '1 kB', + description: 'Description for 1 kB', + } + }, + }, + json: { + name: 'json:test:setting', + ariaName: 'json test setting', + displayName: 'Json test setting', + description: 'Description for Json test setting', + type: 'json', + value: '{"foo": "bar"}', + defVal: '{}', + isCustom: false, + options: null, + }, + markdown: { + name: 'markdown:test:setting', + ariaName: 'markdown test setting', + displayName: 'Markdown test setting', + description: 'Description for Markdown test setting', + type: 'markdown', + value: undefined, + defVal: '', + isCustom: false, + options: null, + }, + number: { + name: 'number:test:setting', + ariaName: 'number test setting', + displayName: 'Number test setting', + description: 'Description for Number test setting', + type: 'number', + value: undefined, + defVal: 5, + isCustom: false, + options: null, + }, + select: { + name: 'select:test:setting', + ariaName: 'select test setting', + displayName: 'Select test setting', + description: 'Description for Select test setting', + type: 'select', + value: undefined, + defVal: 'orange', + isCustom: false, + options: ['apple', 'orange', 'banana'], + }, + string: { + name: 'string:test:setting', + ariaName: 'string test setting', + displayName: 'String test setting', + description: 'Description for String test setting', + type: 'string', + value: undefined, + defVal: null, + isCustom: false, + options: null, + }, +}; +const userValues = { + array: ['user', 'value'], + boolean: false, + image: 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==', + json: '{"hello": "world"}', + markdown: '**bold**', + number: 10, + select: 'banana', + string: 'foo', +}; +const save = jest.fn(() => Promise.resolve()); +const clear = jest.fn(() => Promise.resolve()); + +describe('Field', () => { + Object.keys(settings).forEach(type => { + const setting = settings[type]; + + describe(`for ${type} setting`, () => { + it('should render default value if there is no user value set', async () => { + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render user value if there is user value is set', async () => { + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render custom setting icon if it is custom', async () => { + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); + }); + + if(type === 'image') { + describe(`for changing ${type} setting`, () => { + const component = mount( + + ); + + const userValue = userValues[type]; + component.instance().getImageAsBase64 = (file) => Promise.resolve(file); + + it('should be able to change value from no value and cancel', async () => { + await component.instance().onImageChange([userValue]); + component.update(); + findTestSubject(component, `advancedSetting-cancelEditField-${setting.name}`).simulate('click'); + expect(component.instance().state.unsavedValue === component.instance().state.savedValue).toBe(true); + }); + + it('should be able to change value and save', async () => { + await component.instance().onImageChange([userValue]); + component.update(); + findTestSubject(component, `advancedSetting-saveEditField-${setting.name}`).simulate('click'); + expect(save).toBeCalled(); + component.setState({ savedValue: userValue }); + await component.setProps({ setting: { + ...component.instance().props.setting, + value: userValue, + } }); + component.update(); + }); + + it('should be able to change value from existing value and save', async () => { + const newUserValue = `${userValue}=`; + findTestSubject(component, `advancedSetting-changeImage-${setting.name}`).simulate('click'); + await component.instance().onImageChange([newUserValue]); + component.update(); + findTestSubject(component, `advancedSetting-saveEditField-${setting.name}`).simulate('click'); + expect(save).toBeCalled(); + component.setState({ savedValue: newUserValue }); + await component.setProps({ setting: { + ...component.instance().props.setting, + value: newUserValue, + } }); + component.update(); + }); + + it('should be able to reset to default value', async () => { + findTestSubject(component, `advancedSetting-resetField-${setting.name}`).simulate('click'); + expect(clear).toBeCalled(); + }); + }); + } else if(type === 'markdown' || type === 'json') { + describe(`for changing ${type} setting`, () => { + const component = mount( + + ); + + const userValue = userValues[type]; + const fieldUserValue = userValue; + + it('should be able to change value and cancel', async () => { + component.instance().onCodeEditorChange(fieldUserValue); + component.update(); + findTestSubject(component, `advancedSetting-cancelEditField-${setting.name}`).simulate('click'); + expect(component.instance().state.unsavedValue === component.instance().state.savedValue).toBe(true); + }); + + it('should be able to change value and save', async () => { + component.instance().onCodeEditorChange(fieldUserValue); + component.update(); + findTestSubject(component, `advancedSetting-saveEditField-${setting.name}`).simulate('click'); + expect(save).toBeCalled(); + component.setState({ savedValue: fieldUserValue }); + await component.setProps({ setting: { + ...component.instance().props.setting, + value: userValue, + } }); + component.update(); + }); + + if(type === 'json') { + it('should be able to clear value and have empty object populate', async () => { + component.instance().onCodeEditorChange(''); + component.update(); + expect(component.instance().state.unsavedValue).toEqual('{}'); + }); + } + + it('should be able to reset to default value', async () => { + findTestSubject(component, `advancedSetting-resetField-${setting.name}`).simulate('click'); + expect(clear).toBeCalled(); + }); + }); + } else { + describe(`for changing ${type} setting`, () => { + const component = mount( + + ); + + const userValue = userValues[type]; + const fieldUserValue = type === 'array' ? userValue.join(', ') : userValue; + + it('should be able to change value and cancel', async () => { + component.instance().onFieldChange({ target: { value: fieldUserValue } }); + component.update(); + findTestSubject(component, `advancedSetting-cancelEditField-${setting.name}`).simulate('click'); + expect(component.instance().state.unsavedValue === component.instance().state.savedValue).toBe(true); + }); + + it('should be able to change value and save', async () => { + component.instance().onFieldChange({ target: { value: fieldUserValue } }); + component.update(); + findTestSubject(component, `advancedSetting-saveEditField-${setting.name}`).simulate('click'); + expect(save).toBeCalled(); + component.setState({ savedValue: fieldUserValue }); + await component.setProps({ setting: { + ...component.instance().props.setting, + value: userValue, + } }); + component.update(); + }); + + it('should be able to reset to default value', async () => { + findTestSubject(component, `advancedSetting-resetField-${setting.name}`).simulate('click'); + expect(clear).toBeCalled(); + }); + }); + } + }); +}); diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/field/index.js b/src/core_plugins/kibana/public/management/sections/settings/components/field/index.js new file mode 100644 index 00000000000000..5c86519116fe9f --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/field/index.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { Field } from './field'; diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.js.snap b/src/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.js.snap new file mode 100644 index 00000000000000..627f5d864d1d2a --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/form/__snapshots__/form.test.js.snap @@ -0,0 +1,227 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Form should render no settings message when there are no settings 1`] = ` + + + No settings found + + (Clear search) + + + +`; + +exports[`Form should render normally 1`] = ` + + + + + + + +

+ General +

+
+
+
+ + + +
+
+ +
+ + + + + + +

+ Dashboard +

+
+
+
+ + +
+
+ +
+ + + + + + +

+ X-pack +

+
+ + + Search terms are hiding + 9 + settings + + + (clear search) + + + + +
+
+ + +
+
+ +
+
+`; diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/form/form.js b/src/core_plugins/kibana/public/management/sections/settings/components/form/form.js new file mode 100644 index 00000000000000..951a42eb913b8b --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/form/form.js @@ -0,0 +1,124 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { PureComponent, Fragment } from 'react'; +import PropTypes from 'prop-types'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiForm, + EuiLink, + EuiPanel, + EuiSpacer, + EuiText, +} from '@elastic/eui'; + +import { getCategoryName } from '../../lib'; +import { Field } from '../field'; + +export class Form extends PureComponent { + + static propTypes = { + settings: PropTypes.object.isRequired, + categories: PropTypes.array.isRequired, + categoryCounts: PropTypes.object.isRequired, + clearQuery: PropTypes.func.isRequired, + save: PropTypes.func.isRequired, + clear: PropTypes.func.isRequired, + } + + renderClearQueryLink(totalSettings, currentSettings) { + const { clearQuery } = this.props; + + if(totalSettings !== currentSettings) { + return ( + + + Search terms are hiding {totalSettings - currentSettings} settings {( + + (clear search) + + )} + + + ); + } + + return null; + } + + renderCategory(category, settings, totalSettings) { + return ( + + + + + + +

{getCategoryName(category)}

+
+ {this.renderClearQueryLink(totalSettings, settings.length)} +
+
+ + {settings.map(setting => { + return ( + + ); + })} +
+
+ +
+ ); + } + + render() { + const { settings, categories, categoryCounts, clearQuery } = this.props; + const currentCategories = []; + + categories.forEach(category => { + if(settings[category] && settings[category].length) { + currentCategories.push(category); + } + }); + + return ( + + { + currentCategories.length ? currentCategories.map((category) => { + return ( + this.renderCategory(category, settings[category], categoryCounts[category]) // fix this + ); + }) : ( + + No settings found (Clear search) + + ) + } + + ); + } +} diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/form/form.test.js b/src/core_plugins/kibana/public/management/sections/settings/components/form/form.test.js new file mode 100644 index 00000000000000..cd3b3f2db5fb3e --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/form/form.test.js @@ -0,0 +1,106 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; + +import { Form } from './form'; + +jest.mock('../field', () => ({ + Field: () => { + return 'field'; + } +})); + +const settings = { + 'dashboard': [ + { + name: 'dashboard:test:setting', + ariaName: 'dashboard test setting', + displayName: 'Dashboard test setting', + category: ['dashboard'], + }, + ], + 'general': [ + { + name: 'general:test:date', + ariaName: 'general test date', + displayName: 'Test date', + description: 'bar', + category: ['general'], + }, + { + name: 'setting:test', + ariaName: 'setting test', + displayName: 'Test setting', + description: 'foo', + category: ['general'], + }, + ], + 'x-pack': [ + { + name: 'xpack:test:setting', + ariaName: 'xpack test setting', + displayName: 'X-Pack test setting', + category: ['x-pack'], + description: 'bar', + }, + ], +}; +const categories = ['general', 'dashboard', 'hiddenCategory', 'x-pack']; +const categoryCounts = { + general: 2, + dashboard: 1, + 'x-pack': 10, +}; +const save = () => {}; +const clear = () => {}; +const clearQuery = () => {}; + +describe('Form', () => { + it('should render normally', async () => { + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should render no settings message when there are no settings', async () => { + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/form/index.js b/src/core_plugins/kibana/public/management/sections/settings/components/form/index.js new file mode 100644 index 00000000000000..979ae179519ca1 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/form/index.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { Form } from './form'; diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/search/__snapshots__/search.test.js.snap b/src/core_plugins/kibana/public/management/sections/settings/components/search/__snapshots__/search.test.js.snap new file mode 100644 index 00000000000000..126e311afed782 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/search/__snapshots__/search.test.js.snap @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Search should render normally 1`] = ` + +`; diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/search/index.js b/src/core_plugins/kibana/public/management/sections/settings/components/search/index.js new file mode 100644 index 00000000000000..873bddda904402 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/search/index.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { Search } from './search'; diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/search/search.js b/src/core_plugins/kibana/public/management/sections/settings/components/search/search.js new file mode 100644 index 00000000000000..e60ffee7bb6efd --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/search/search.js @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; + +import { + EuiSearchBar, +} from '@elastic/eui'; + +import { getCategoryName } from '../../lib'; + +export class Search extends PureComponent { + + static propTypes = { + categories: PropTypes.array.isRequired, + query: PropTypes.object.isRequired, + onQueryChange: PropTypes.func.isRequired, + }; + + constructor(props) { + super(props); + const { categories } = props; + this.categories = categories.map(category => { + return { + value: category, + name: getCategoryName(category), + }; + }); + } + + render() { + const { query, onQueryChange } = this.props; + + const box = { + incremental: true, + }; + + const filters = [ + { + type: 'field_value_selection', + field: 'category', + name: 'Category', + multiSelect: 'or', + options: this.categories, + } + ]; + + return ( + + ); + } +} diff --git a/src/core_plugins/kibana/public/management/sections/settings/components/search/search.test.js b/src/core_plugins/kibana/public/management/sections/settings/components/search/search.test.js new file mode 100644 index 00000000000000..184fe17a2e855c --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/components/search/search.test.js @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallow, mount } from 'enzyme'; + +import { Query } from '@elastic/eui'; +import { Search } from './search'; + +const query = Query.parse(''); +const categories = ['general', 'dashboard', 'hiddenCategory', 'x-pack']; + +describe('Search', () => { + it('should render normally', async () => { + const onQueryChange = () => {}; + const component = shallow( + + ); + + expect(component).toMatchSnapshot(); + }); + + it('should call parent function when query is changed', async () => { + const onQueryChange = jest.fn(); + const component = mount( + + ); + component.find('input').simulate('keyUp'); + component.find('EuiSearchFilters').prop('onChange')(query); + expect(onQueryChange).toHaveBeenCalledTimes(2); + }); +}); diff --git a/src/core_plugins/kibana/public/management/sections/settings/index.html b/src/core_plugins/kibana/public/management/sections/settings/index.html index c7630160df904c..e0544029d3079c 100644 --- a/src/core_plugins/kibana/public/management/sections/settings/index.html +++ b/src/core_plugins/kibana/public/management/sections/settings/index.html @@ -1,77 +1,5 @@ - - -
-
- - - Caution: You can break stuff here - -
- -
-
- Be careful in here, these settings are for very advanced users only. - Tweaks you make here can break large portions of Kibana. Some of these - settings may be undocumented, unsupported or experimental. If a field has a default value, - blanking the field will reset it to its default which - may be unacceptable given other configuration directives. Deleting a - custom setting will permanently remove it from Kibana's config. -
-
-
- - - -
- - -
- - - - - - - - - - - - - - - -
-
- Name -
-
-
- Value -
-
-
- -
-
+ +
diff --git a/src/core_plugins/kibana/public/management/sections/settings/index.js b/src/core_plugins/kibana/public/management/sections/settings/index.js index f5e9a75027c850..d037cd16c74280 100644 --- a/src/core_plugins/kibana/public/management/sections/settings/index.js +++ b/src/core_plugins/kibana/public/management/sections/settings/index.js @@ -1,41 +1,75 @@ -import _ from 'lodash'; -import { toEditableConfig } from './lib/to_editable_config'; -import './advanced_row'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { management } from 'ui/management'; import uiRoutes from 'ui/routes'; import { uiModules } from 'ui/modules'; import indexTemplate from './index.html'; import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { AdvancedSettings } from './advanced_settings'; + +const REACT_ADVANCED_SETTINGS_DOM_ELEMENT_ID = 'reactAdvancedSettings'; + +function updateAdvancedSettings($scope, config, query) { + $scope.$$postDigest(() => { + const node = document.getElementById(REACT_ADVANCED_SETTINGS_DOM_ELEMENT_ID); + if (!node) { + return; + } + + render( + , + node, + ); + }); +} + +function destroyAdvancedSettings() { + const node = document.getElementById(REACT_ADVANCED_SETTINGS_DOM_ELEMENT_ID); + node && unmountComponentAtNode(node); +} + uiRoutes - .when('/management/kibana/settings', { + .when('/management/kibana/settings/:setting?', { template: indexTemplate }); uiModules.get('apps/management') - .directive('kbnManagementAdvanced', function (config) { + .directive('kbnManagementAdvanced', function (config, $route) { return { restrict: 'E', link: function ($scope) { - // react to changes of the config values - config.watchAll(changed, $scope); - - // initial config setup - changed(); - - function changed() { - const all = config.getAll(); - const editable = _(all) - .map((def, name) => toEditableConfig({ - def, - name, - value: def.userValue, - isCustom: config.isCustom(name) - })) - .value(); - const writable = _.reject(editable, 'readonly'); - $scope.configs = writable; - } + config.watchAll(() => { + updateAdvancedSettings($scope, config, $route.current.params.setting || ''); + }, $scope); + + $scope.$on('$destory', () => { + destroyAdvancedSettings(); + }); + + $route.updateParams({ setting: null }); } }; }); @@ -51,7 +85,7 @@ FeatureCatalogueRegistryProvider.register(() => { id: 'advanced_settings', title: 'Advanced Settings', description: 'Directly edit settings that control behavior in Kibana.', - icon: '/plugins/kibana/assets/app_advanced_settings.svg', + icon: 'advancedSettingsApp', path: '/app/kibana#/management/kibana/settings', showOnHomePage: false, category: FeatureCatalogueCategory.ADMIN diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js new file mode 100644 index 00000000000000..f3b15caa926370 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/default_category.test.js @@ -0,0 +1,31 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; +import { DEFAULT_CATEGORY } from '../default_category'; + +describe('Settings', function () { + describe('Advanced', function () { + describe('DEFAULT_CATEGORY', function () { + it('should be general', function () { + expect(DEFAULT_CATEGORY).to.be('general'); + }); + }); + }); +}); diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.js b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js similarity index 52% rename from src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.js rename to src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js index f8c02e6dac00ec..59606b6677b40a 100644 --- a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.js +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_aria_name.test.js @@ -1,6 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ -import { getAriaName } from '../get_aria_name'; import expect from 'expect.js'; +import { getAriaName } from '../get_aria_name'; describe('Settings', function () { describe('Advanced', function () { diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js new file mode 100644 index 00000000000000..939eca86afed25 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_category_name.test.js @@ -0,0 +1,52 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; +import { getCategoryName } from '../get_category_name'; + +describe('Settings', function () { + describe('Advanced', function () { + describe('getCategoryName(category)', function () { + it('should be a function', function () { + expect(getCategoryName).to.be.a(Function); + }); + + it('should return correct name for known categories', function () { + expect(getCategoryName('general')).to.be('General'); + expect(getCategoryName('timelion')).to.be('Timelion'); + expect(getCategoryName('notifications')).to.be('Notifications'); + expect(getCategoryName('visualizations')).to.be('Visualizations'); + expect(getCategoryName('discover')).to.be('Discover'); + expect(getCategoryName('dashboard')).to.be('Dashboard'); + expect(getCategoryName('reporting')).to.be('Reporting'); + expect(getCategoryName('search')).to.be('Search'); + }); + + it('should capitalize unknown category', function () { + expect(getCategoryName('elasticsearch')).to.be('Elasticsearch'); + }); + + it('should return empty string for no category', function () { + expect(getCategoryName()).to.be(''); + expect(getCategoryName('')).to.be(''); + expect(getCategoryName(false)).to.be(''); + }); + }); + }); +}); diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_editor_type.js b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_editor_type.js deleted file mode 100644 index b1de3c48593fbf..00000000000000 --- a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_editor_type.js +++ /dev/null @@ -1,27 +0,0 @@ - -import { getEditorType } from '../get_editor_type'; -import expect from 'expect.js'; - -describe('Settings', function () { - describe('Advanced', function () { - describe('getEditorType(conf)', function () { - describe('when given type has a named editor', function () { - it('returns that named editor', function () { - expect(getEditorType({ type: 'json' })).to.equal('json'); - expect(getEditorType({ type: 'array' })).to.equal('array'); - expect(getEditorType({ type: 'boolean' })).to.equal('boolean'); - expect(getEditorType({ type: 'select' })).to.equal('select'); - }); - }); - - describe('when given a type of number, string, null, or undefined', function () { - it('returns "normal"', function () { - expect(getEditorType({ type: 'number' })).to.equal('normal'); - expect(getEditorType({ type: 'string' })).to.equal('normal'); - expect(getEditorType({ type: 'null' })).to.equal('normal'); - expect(getEditorType({ type: 'undefined' })).to.equal('normal'); - }); - }); - }); - }); -}); diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.js b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js similarity index 64% rename from src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.js rename to src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js index 4c3b3102a52f6d..212e9c94f37e9f 100644 --- a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.js +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/get_val_type.test.js @@ -1,6 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ -import { getValType } from '../get_val_type'; import expect from 'expect.js'; +import { getValType } from '../get_val_type'; describe('Settings', function () { describe('Advanced', function () { diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js new file mode 100644 index 00000000000000..d668c6ff1dbc8f --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/is_default_value.test.js @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; +import { isDefaultValue } from '../is_default_value'; + +describe('Settings', function () { + describe('Advanced', function () { + describe('getCategoryName(category)', function () { + it('should be a function', function () { + expect(isDefaultValue).to.be.a(Function); + }); + + describe('when given a setting definition object', function () { + const setting = { + isCustom: false, + value: 'value', + defVal: 'defaultValue', + }; + + describe('that is custom', function () { + it('should return true', function () { + expect(isDefaultValue({ ...setting, isCustom: true })).to.be(true); + }); + }); + + describe('without a value', function () { + it('should return true', function () { + expect(isDefaultValue({ ...setting, value: undefined })).to.be(true); + expect(isDefaultValue({ ...setting, value: '' })).to.be(true); + }); + }); + + describe('with a value that is the same as the default value', function () { + it('should return true', function () { + expect(isDefaultValue({ ...setting, value: 'defaultValue' })).to.be(true); + expect(isDefaultValue({ ...setting, value: [], defVal: [] })).to.be(true); + expect(isDefaultValue({ ...setting, value: '{"foo":"bar"}', defVal: '{"foo":"bar"}' })).to.be(true); + expect(isDefaultValue({ ...setting, value: 123, defVal: 123 })).to.be(true); + expect(isDefaultValue({ ...setting, value: 456, defVal: '456' })).to.be(true); + expect(isDefaultValue({ ...setting, value: false, defVal: false })).to.be(true); + }); + }); + + describe('with a value that is different than the default value', function () { + it('should return false', function () { + expect(isDefaultValue({ ...setting })).to.be(false); + expect(isDefaultValue({ ...setting, value: [1], defVal: [2] })).to.be(false); + expect(isDefaultValue({ ...setting, value: '{"foo":"bar"}', defVal: '{"foo2":"bar2"}' })).to.be(false); + expect(isDefaultValue({ ...setting, value: 123, defVal: 1234 })).to.be(false); + expect(isDefaultValue({ ...setting, value: 456, defVal: '4567' })).to.be(false); + expect(isDefaultValue({ ...setting, value: true, defVal: false })).to.be(false); + }); + }); + }); + }); + }); +}); diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.js b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js similarity index 76% rename from src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.js rename to src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js index 55d16bf1a8aef9..428b9852ff842f 100644 --- a/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.js +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/__tests__/to_editable_config.test.js @@ -1,6 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ -import { toEditableConfig } from '../to_editable_config'; import expect from 'expect.js'; +import { toEditableConfig } from '../to_editable_config'; describe('Settings', function () { describe('Advanced', function () { diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/default_category.js b/src/core_plugins/kibana/public/management/sections/settings/lib/default_category.js new file mode 100644 index 00000000000000..01cc9c5113c28a --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/default_category.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const DEFAULT_CATEGORY = 'general'; diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.js b/src/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.js index 96389e862f8365..16fd6de8273df2 100644 --- a/src/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.js +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/get_aria_name.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { words } from 'lodash'; diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.js b/src/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.js new file mode 100644 index 00000000000000..cad3f28a5ad16a --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/get_category_name.js @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { StringUtils } from 'ui/utils/string_utils'; + +const names = { + 'general': 'General', + 'timelion': 'Timelion', + 'notifications': 'Notifications', + 'visualizations': 'Visualizations', + 'discover': 'Discover', + 'dashboard': 'Dashboard', + 'reporting': 'Reporting', + 'search': 'Search', +}; + +export function getCategoryName(category) { + return category ? names[category] || StringUtils.upperFirst(category) : ''; +} diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/get_editor_type.js b/src/core_plugins/kibana/public/management/sections/settings/lib/get_editor_type.js deleted file mode 100644 index 2fad54df7b1c87..00000000000000 --- a/src/core_plugins/kibana/public/management/sections/settings/lib/get_editor_type.js +++ /dev/null @@ -1,13 +0,0 @@ -import _ from 'lodash'; - -const NAMED_EDITORS = ['json', 'array', 'boolean', 'select', 'markdown', 'image']; -const NORMAL_EDITOR = ['number', 'string', 'null', 'undefined']; - -/** - * @param {object} advanced setting configuration object - * @returns {string} the editor type to use when editing value - */ -export function getEditorType(conf) { - if (_.contains(NAMED_EDITORS, conf.type)) return conf.type; - if (_.contains(NORMAL_EDITOR, conf.type)) return 'normal'; -} diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.js b/src/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.js index b674121bb04cef..0035ed9babd310 100644 --- a/src/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.js +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/get_val_type.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * @param {object} advanced setting definition object * @param {?} current value of the setting diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/index.js b/src/core_plugins/kibana/public/management/sections/settings/lib/index.js new file mode 100644 index 00000000000000..e88d1cb131b522 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/index.js @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { isDefaultValue } from './is_default_value'; +export { toEditableConfig } from './to_editable_config'; +export { getCategoryName } from './get_category_name'; +export { DEFAULT_CATEGORY } from './default_category'; +export { getAriaName } from './get_aria_name'; diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.js b/src/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.js new file mode 100644 index 00000000000000..1a14c05a84c835 --- /dev/null +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/is_default_value.js @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export function isDefaultValue(setting) { + return (setting.isCustom || setting.value === undefined || setting.value === '' || String(setting.value) === String(setting.defVal)); +} diff --git a/src/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js b/src/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js index 2e72277a8db882..f152f3f5a3ddf6 100644 --- a/src/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js +++ b/src/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js @@ -1,6 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { getValType } from './get_val_type'; -import { getEditorType } from './get_editor_type'; import { getAriaName } from './get_aria_name'; +import { DEFAULT_CATEGORY } from './default_category'; /** * @param {object} advanced setting definition object @@ -14,26 +33,18 @@ export function toEditableConfig({ def, name, value, isCustom }) { } const conf = { name, + displayName: def.name || name, ariaName: getAriaName(name), value, + category: def.category && def.category.length ? def.category : [DEFAULT_CATEGORY], isCustom, readonly: !!def.readonly, defVal: def.value, type: getValType(def, value), description: def.description, - options: def.options + options: def.options, }; - const editor = getEditorType(conf); - conf.json = editor === 'json'; - conf.select = editor === 'select'; - conf.bool = editor === 'boolean'; - conf.array = editor === 'array'; - conf.markdown = editor === 'markdown'; - conf.image = editor === 'image'; - conf.normal = editor === 'normal'; - conf.tooComplex = !editor; - return conf; } diff --git a/src/core_plugins/kibana/public/management/styles/main.less b/src/core_plugins/kibana/public/management/styles/main.less index 402fee56a2a33a..783cd1e9cb6301 100644 --- a/src/core_plugins/kibana/public/management/styles/main.less +++ b/src/core_plugins/kibana/public/management/styles/main.less @@ -24,6 +24,11 @@ kbn-management-objects-view { text-transform: capitalize; } +kbn-management-objects { + background: @globalColorLightestGray; + min-height: 100vh; +} + kbn-management-app { li.current-page { font-size: 1.5em; diff --git a/src/core_plugins/kibana/public/reducers.js b/src/core_plugins/kibana/public/reducers.js index 85894b1b69ce74..6d6d2063e5017a 100644 --- a/src/core_plugins/kibana/public/reducers.js +++ b/src/core_plugins/kibana/public/reducers.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { combineReducers } from 'redux'; import { dashboard } from './dashboard/reducers'; diff --git a/src/core_plugins/kibana/public/selectors/dashboard_selectors.js b/src/core_plugins/kibana/public/selectors/dashboard_selectors.js index ca124c60490dd2..3d72b010e81b57 100644 --- a/src/core_plugins/kibana/public/selectors/dashboard_selectors.js +++ b/src/core_plugins/kibana/public/selectors/dashboard_selectors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import * as DashboardSelectors from '../dashboard/selectors'; /** diff --git a/src/core_plugins/kibana/public/selectors/index.js b/src/core_plugins/kibana/public/selectors/index.js index fa3c645d3717b1..a7453b460be916 100644 --- a/src/core_plugins/kibana/public/selectors/index.js +++ b/src/core_plugins/kibana/public/selectors/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export * from './dashboard_selectors'; diff --git a/src/core_plugins/kibana/public/store.js b/src/core_plugins/kibana/public/store.js index ff0f58161c0187..f877195a248d30 100644 --- a/src/core_plugins/kibana/public/store.js +++ b/src/core_plugins/kibana/public/store.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { createStore, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; diff --git a/src/core_plugins/kibana/public/visualize/editor/agg_filter.js b/src/core_plugins/kibana/public/visualize/editor/agg_filter.js index 0ce931b37b7795..782a8fa7a154aa 100644 --- a/src/core_plugins/kibana/public/visualize/editor/agg_filter.js +++ b/src/core_plugins/kibana/public/visualize/editor/agg_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { propFilter } from 'ui/filters/_prop_filter'; import { uiModules } from 'ui/modules'; diff --git a/src/core_plugins/kibana/public/visualize/editor/editor.js b/src/core_plugins/kibana/public/visualize/editor/editor.js index 8284a8d4203c81..a4a0dbe96efb5a 100644 --- a/src/core_plugins/kibana/public/visualize/editor/editor.js +++ b/src/core_plugins/kibana/public/visualize/editor/editor.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import '../saved_visualizations/saved_visualizations'; import 'ui/vis/editors/default/sidebar'; diff --git a/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.js b/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.js index 271aff81f5d3f8..dc4ba34c3824b7 100644 --- a/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.js +++ b/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { PersistedState } from 'ui/persisted_state'; import { Embeddable } from 'ui/embeddable'; import chrome from 'ui/chrome'; @@ -36,27 +55,15 @@ export class VisualizeEmbeddable extends Embeddable { }; } - getHandlerParams() { - return { - uiState: this.uiState, - // Append visualization to container instead of replacing its content - append: true, - timeRange: this.timeRange, - cssClass: `panel-content panel-content--fullWidth`, - // The chrome is permanently hidden in "embed mode" in which case we don't want to show the spy pane, since - // we deem that situation to be more public facing and want to hide more detailed information. - showSpyPanel: !chrome.getIsChromePermanentlyHidden(), - dataAttrs: { - 'shared-item': '', - title: this.panelTitle, - description: this.savedVisualization.description, - } - }; - } - - onContainerStateChanged(containerState) { + /** + * Transfers all changes in the containerState.embeddableCustomization into + * the uiState of this visualization. + */ + transferCustomizationsToUiState(containerState) { + // Check for changes that need to be forwarded to the uiState + // Since the vis has an own listener on the uiState we don't need to + // pass anything from here to the handler.update method const customization = containerState.embeddableCustomization; - let isDirty = false; if (!_.isEqual(this.customization, customization)) { // Turn this off or the uiStateChangeHandler will fire for every modification. this.uiState.off('change', this._uiStateChangeHandler); @@ -65,40 +72,80 @@ export class VisualizeEmbeddable extends Embeddable { this.uiState.set(key, customization[key]); }); this.customization = customization; - isDirty = true; this.uiState.on('change', this._uiStateChangeHandler); } + } + /** + * Retrieve the panel title for this panel from the container state. + * This will either return the overwritten panel title or the visualization title. + */ + getPanelTitle(containerState) { let derivedPanelTitle = ''; if (!containerState.hidePanelTitles) { derivedPanelTitle = containerState.customTitle !== undefined ? containerState.customTitle : this.savedVisualization.title; } + return derivedPanelTitle; + } + onContainerStateChanged(containerState) { + this.transferCustomizationsToUiState(containerState); + + const updatedParams = {}; + + // Check if timerange has changed + if (containerState.timeRange !== this.timeRange) { + updatedParams.timeRange = containerState.timeRange; + this.timeRange = containerState.timeRange; + } + + const derivedPanelTitle = this.getPanelTitle(containerState); if (this.panelTitle !== derivedPanelTitle) { + updatedParams.dataAttrs = { + title: derivedPanelTitle, + }; this.panelTitle = derivedPanelTitle; - isDirty = true; } - if (isDirty && this.handler && this.domNode) { - // TODO: We need something like this in the handler - // this.handler.update(this.getHandlerParams()); - // For now: - this.destroy(); - this.handler = this.loader.embedVisualizationWithSavedObject( - this.domNode, - this.savedVisualization, - this.getHandlerParams()); + if (this.handler && !_.isEmpty(updatedParams)) { + this.handler.update(updatedParams); } } - render(domNode) { - this.domNode = domNode; + /** + * + * @param {Element} domNode + * @param {ContainerState} containerState + */ + render(domNode, containerState) { + this.panelTitle = this.getPanelTitle(containerState); + this.timeRange = containerState.timeRange; + + this.transferCustomizationsToUiState(containerState); + + const handlerParams = { + uiState: this.uiState, + // Append visualization to container instead of replacing its content + append: true, + timeRange: containerState.timeRange, + cssClass: `panel-content panel-content--fullWidth`, + // The chrome is permanently hidden in "embed mode" in which case we don't want to show the spy pane, since + // we deem that situation to be more public facing and want to hide more detailed information. + showSpyPanel: !chrome.getIsChromePermanentlyHidden(), + dataAttrs: { + 'shared-item': '', + title: this.panelTitle, + description: this.savedVisualization.description, + } + }; + this.handler = this.loader.embedVisualizationWithSavedObject( domNode, this.savedVisualization, - this.getHandlerParams()); + handlerParams, + ); } destroy() { diff --git a/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.js b/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.js index ea9fba9481da8d..bcc560fe40b3c9 100644 --- a/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.js +++ b/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import { getVisualizeLoader } from 'ui/visualize/loader'; import { EmbeddableFactory, Embeddable } from 'ui/embeddable'; diff --git a/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory_provider.js b/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory_provider.js index 05c52b9d244806..e96fe521eb16ca 100644 --- a/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory_provider.js +++ b/src/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory_provider.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VisualizeEmbeddableFactory } from './visualize_embeddable_factory'; import { EmbeddableFactoriesRegistryProvider } from 'ui/embeddable/embeddable_factories_registry'; diff --git a/src/core_plugins/kibana/public/visualize/index.js b/src/core_plugins/kibana/public/visualize/index.js index a5616ca39d4db5..c7b57bcb75f5a2 100644 --- a/src/core_plugins/kibana/public/visualize/index.js +++ b/src/core_plugins/kibana/public/visualize/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './styles/main.less'; import './editor/editor'; import './wizard/wizard'; @@ -30,7 +49,7 @@ FeatureCatalogueRegistryProvider.register(() => { id: 'visualize', title: 'Visualize', description: 'Create visualizations and aggregate data stores in your Elasticsearch indices.', - icon: '/plugins/kibana/assets/app_visualize.svg', + icon: 'visualizeApp', path: `/app/kibana#${VisualizeConstants.LANDING_PAGE_PATH}`, showOnHomePage: true, category: FeatureCatalogueCategory.DATA diff --git a/src/core_plugins/kibana/public/visualize/listing/no_visualizations_prompt.js b/src/core_plugins/kibana/public/visualize/listing/no_visualizations_prompt.js index cbdac6f267befd..8a2ed4f3310bbc 100644 --- a/src/core_plugins/kibana/public/visualize/listing/no_visualizations_prompt.js +++ b/src/core_plugins/kibana/public/visualize/listing/no_visualizations_prompt.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { diff --git a/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js b/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js index a4a61e0c0a80c1..c9272c1b6cf299 100644 --- a/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js +++ b/src/core_plugins/kibana/public/visualize/listing/visualize_listing.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; import 'ui/pager_control'; import 'ui/pager'; diff --git a/src/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js b/src/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js index 9f407c97e6602d..6f41435d7c2594 100644 --- a/src/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js +++ b/src/core_plugins/kibana/public/visualize/listing/visualize_listing_table.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component } from 'react'; import PropTypes from 'prop-types'; import _ from 'lodash'; diff --git a/src/core_plugins/kibana/public/visualize/saved_visualizations/_saved_vis.js b/src/core_plugins/kibana/public/visualize/saved_visualizations/_saved_vis.js index b769552113cf0e..dbc3370808bb86 100644 --- a/src/core_plugins/kibana/public/visualize/saved_visualizations/_saved_vis.js +++ b/src/core_plugins/kibana/public/visualize/saved_visualizations/_saved_vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * @name SavedVis * @@ -78,17 +97,6 @@ uiModules self.searchSource.size(0); return self.vis ? self._updateVis() : self._createVis(); - }) - .then(function () { - self.searchSource.onRequestStart((searchSource, searchRequest) => { - return self.vis.onSearchRequestStart(searchSource, searchRequest); - }); - - self.searchSource.aggs(function () { - return self.vis.aggs.toDsl(); - }); - - return self; }); }; diff --git a/src/core_plugins/kibana/public/visualize/saved_visualizations/index.js b/src/core_plugins/kibana/public/visualize/saved_visualizations/index.js index 92b7dc0944c281..62bf106adc0d00 100644 --- a/src/core_plugins/kibana/public/visualize/saved_visualizations/index.js +++ b/src/core_plugins/kibana/public/visualize/saved_visualizations/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './saved_visualizations'; diff --git a/src/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualization_register.js b/src/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualization_register.js index aeb61e2d5a78da..8bb56b12497960 100644 --- a/src/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualization_register.js +++ b/src/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualization_register.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; import './saved_visualizations'; diff --git a/src/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.js b/src/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.js index 7a790b4cb47514..4d1735acfba310 100644 --- a/src/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.js +++ b/src/core_plugins/kibana/public/visualize/saved_visualizations/saved_visualizations.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './_saved_vis'; import { VisTypesRegistryProvider } from 'ui/registry/vis_types'; import { uiModules } from 'ui/modules'; diff --git a/src/core_plugins/kibana/public/visualize/visualize_constants.js b/src/core_plugins/kibana/public/visualize/visualize_constants.js index eddc7bac7daedc..ae1b4c06af6083 100644 --- a/src/core_plugins/kibana/public/visualize/visualize_constants.js +++ b/src/core_plugins/kibana/public/visualize/visualize_constants.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const VisualizeConstants = { LANDING_PAGE_PATH: '/visualize', WIZARD_STEP_1_PAGE_PATH: '/visualize/new', diff --git a/src/core_plugins/kibana/public/visualize/wizard/wizard.js b/src/core_plugins/kibana/public/visualize/wizard/wizard.js index 2a2b5552bed25e..699bb5ade66b35 100644 --- a/src/core_plugins/kibana/public/visualize/wizard/wizard.js +++ b/src/core_plugins/kibana/public/visualize/wizard/wizard.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import '../saved_visualizations/saved_visualizations'; import 'ui/directives/saved_object_finder'; import 'ui/directives/paginated_selectable_list'; diff --git a/src/core_plugins/kibana/server/field_formats/register.js b/src/core_plugins/kibana/server/field_formats/register.js index 9861e49b492964..5d3ec472d82937 100644 --- a/src/core_plugins/kibana/server/field_formats/register.js +++ b/src/core_plugins/kibana/server/field_formats/register.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { createUrlFormat } from '../../common/field_formats/types/url'; import { createBytesFormat } from '../../common/field_formats/types/bytes'; import { createDateFormat } from '../../common/field_formats/types/date'; diff --git a/src/core_plugins/kibana/server/lib/__tests__/handle_es_error.js b/src/core_plugins/kibana/server/lib/__tests__/handle_es_error.js index b2d98d73b0a917..a3cd660687897d 100644 --- a/src/core_plugins/kibana/server/lib/__tests__/handle_es_error.js +++ b/src/core_plugins/kibana/server/lib/__tests__/handle_es_error.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import handleESError from '../handle_es_error'; import { errors as esErrors } from 'elasticsearch'; diff --git a/src/core_plugins/kibana/server/lib/__tests__/manage_uuid.js b/src/core_plugins/kibana/server/lib/__tests__/manage_uuid.js index 216292c6c4de57..dc0663d4aabe52 100644 --- a/src/core_plugins/kibana/server/lib/__tests__/manage_uuid.js +++ b/src/core_plugins/kibana/server/lib/__tests__/manage_uuid.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import sinon from 'sinon'; import * as kbnTestServer from '../../../../../test_utils/kbn_server.js'; @@ -20,7 +39,6 @@ describe('core_plugins/kibana/server/lib', function () { // clear uuid stuff from previous test runs beforeEach(function () { kbnServer.server.log = sinon.stub(); - kbnServer.server.log.reset(); config = kbnServer.server.config(); }); diff --git a/src/core_plugins/kibana/server/lib/__tests__/relationships.js b/src/core_plugins/kibana/server/lib/__tests__/relationships.js new file mode 100644 index 00000000000000..371f18462ed91a --- /dev/null +++ b/src/core_plugins/kibana/server/lib/__tests__/relationships.js @@ -0,0 +1,306 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; +import { findRelationships } from '../management/saved_objects/relationships'; + +describe('findRelationships', () => { + it('should find relationships for dashboards', async () => { + const type = 'dashboard'; + const id = 'foo'; + const size = 10; + + const savedObjectsClient = { + _index: '.kibana', + get: () => ({ + attributes: { + panelsJSON: JSON.stringify([{ id: '1' }, { id: '2' }, { id: '3' }]), + }, + }), + bulkGet: () => ({ + saved_objects: [ + { + id: '1', + attributes: { + title: 'Foo', + }, + }, + { + id: '2', + attributes: { + title: 'Bar', + }, + }, + { + id: '3', + attributes: { + title: 'FooBar', + }, + }, + ], + }) + }; + const result = await findRelationships( + type, + id, + size, + savedObjectsClient + ); + expect(result).to.eql({ + visualizations: [ + { id: '1', title: 'Foo' }, + { id: '2', title: 'Bar' }, + { id: '3', title: 'FooBar' }, + ], + }); + }); + + it('should find relationships for visualizations', async () => { + const type = 'visualization'; + const id = 'foo'; + const size = 10; + + const savedObjectsClient = { + find: () => ({ + saved_objects: [ + { + id: '1', + attributes: { + title: 'My Dashboard', + panelsJSON: JSON.stringify([ + { + type: 'visualization', + id, + }, + { + type: 'visualization', + id: 'foobar', + }, + ]), + }, + }, + { + id: '2', + attributes: { + title: 'Your Dashboard', + panelsJSON: JSON.stringify([ + { + type: 'visualization', + id, + }, + { + type: 'visualization', + id: 'foobar', + }, + ]), + }, + }, + ] + }) + }; + + const result = await findRelationships( + type, + id, + size, + savedObjectsClient + ); + expect(result).to.eql({ + dashboards: [ + { id: '1', title: 'My Dashboard' }, + { id: '2', title: 'Your Dashboard' }, + ], + }); + }); + + it('should find relationships for saved searches', async () => { + const type = 'search'; + const id = 'foo'; + const size = 10; + + const savedObjectsClient = { + get: type => { + if (type === 'search') { + return { + id: '1', + attributes: { + kibanaSavedObjectMeta: { + searchSourceJSON: JSON.stringify({ + index: 'index-pattern:1', + }), + }, + }, + }; + } + + return { + id: 'index-pattern:1', + attributes: { + title: 'My Index Pattern', + }, + }; + }, + find: () => ({ + saved_objects: [ + { + id: '1', + attributes: { + title: 'Foo', + }, + }, + { + id: '2', + attributes: { + title: 'Bar', + }, + }, + { + id: '3', + attributes: { + title: 'FooBar', + }, + }, + ] + }) + }; + + const result = await findRelationships( + type, + id, + size, + savedObjectsClient + ); + expect(result).to.eql({ + visualizations: [ + { id: '1', title: 'Foo' }, + { id: '2', title: 'Bar' }, + { id: '3', title: 'FooBar' }, + ], + indexPatterns: [{ id: 'index-pattern:1', title: 'My Index Pattern' }], + }); + }); + + it('should find relationships for index patterns', async () => { + const type = 'index-pattern'; + const id = 'foo'; + const size = 10; + + const savedObjectsClient = { + find: options => { + if (options.type === 'visualization') { + return { + saved_objects: [ + { + id: '1', + found: true, + attributes: { + title: 'Foo', + kibanaSavedObjectMeta: { + searchSourceJSON: JSON.stringify({ + index: 'foo', + }), + }, + }, + }, + { + id: '2', + found: true, + attributes: { + title: 'Bar', + kibanaSavedObjectMeta: { + searchSourceJSON: JSON.stringify({ + index: 'foo', + }), + }, + }, + }, + { + id: '3', + found: true, + attributes: { + title: 'FooBar', + kibanaSavedObjectMeta: { + searchSourceJSON: JSON.stringify({ + index: 'foo2', + }), + }, + }, + }, + ] + }; + } + + return { + saved_objects: [ + { + id: '1', + attributes: { + title: 'Foo', + kibanaSavedObjectMeta: { + searchSourceJSON: JSON.stringify({ + index: 'foo', + }), + }, + }, + }, + { + id: '2', + attributes: { + title: 'Bar', + kibanaSavedObjectMeta: { + searchSourceJSON: JSON.stringify({ + index: 'foo', + }), + }, + }, + }, + { + id: '3', + attributes: { + title: 'FooBar', + kibanaSavedObjectMeta: { + searchSourceJSON: JSON.stringify({ + index: 'foo2', + }), + }, + }, + }, + ] + }; + } + }; + + const result = await findRelationships( + type, + id, + size, + savedObjectsClient + ); + expect(result).to.eql({ + visualizations: [{ id: '1', title: 'Foo' }, { id: '2', title: 'Bar' }], + searches: [{ id: '1', title: 'Foo' }, { id: '2', title: 'Bar' }], + }); + }); + + it('should return an empty object for invalid types', async () => { + const type = 'invalid'; + const result = await findRelationships(type); + expect(result).to.eql({}); + }); +}); diff --git a/src/core_plugins/kibana/server/lib/__tests__/system_api.js b/src/core_plugins/kibana/server/lib/__tests__/system_api.js index f019d354e37b96..c8b9cefc5aa1ba 100644 --- a/src/core_plugins/kibana/server/lib/__tests__/system_api.js +++ b/src/core_plugins/kibana/server/lib/__tests__/system_api.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { isSystemApiRequest } from '../system_api'; diff --git a/src/core_plugins/kibana/server/lib/export/__tests__/collect_dashboards.js b/src/core_plugins/kibana/server/lib/export/__tests__/collect_dashboards.js index 14e28bba70045a..fbbe0cc6e37014 100644 --- a/src/core_plugins/kibana/server/lib/export/__tests__/collect_dashboards.js +++ b/src/core_plugins/kibana/server/lib/export/__tests__/collect_dashboards.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import * as deps from '../collect_panels'; import { collectDashboards } from '../collect_dashboards'; @@ -6,7 +25,7 @@ import { expect } from 'chai'; describe('collectDashboards(req, ids)', () => { let collectPanelsStub; - const savedObjectsClient = { bulkGet: sinon.mock() }; + const savedObjectsClient = { bulkGet: sinon.stub() }; const ids = ['dashboard-01', 'dashboard-02']; @@ -32,7 +51,7 @@ describe('collectDashboards(req, ids)', () => { afterEach(() => { collectPanelsStub.restore(); - savedObjectsClient.bulkGet.reset(); + savedObjectsClient.bulkGet.resetHistory(); }); it('should request all dashboards', async () => { diff --git a/src/core_plugins/kibana/server/lib/export/__tests__/collect_index_patterns.js b/src/core_plugins/kibana/server/lib/export/__tests__/collect_index_patterns.js index fe07e9d8d5519b..edbb8ecbf10b3c 100644 --- a/src/core_plugins/kibana/server/lib/export/__tests__/collect_index_patterns.js +++ b/src/core_plugins/kibana/server/lib/export/__tests__/collect_index_patterns.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import { collectIndexPatterns } from '../collect_index_patterns'; import { expect } from 'chai'; @@ -32,7 +51,7 @@ describe('collectIndexPatterns(req, panels)', () => { } ]; - const savedObjectsClient = { bulkGet: sinon.mock() }; + const savedObjectsClient = { bulkGet: sinon.stub() }; beforeEach(() => { savedObjectsClient.bulkGet.returns(Promise.resolve({ @@ -43,7 +62,7 @@ describe('collectIndexPatterns(req, panels)', () => { }); afterEach(() => { - savedObjectsClient.bulkGet.reset(); + savedObjectsClient.bulkGet.resetHistory(); }); it('should request all index patterns', async () => { diff --git a/src/core_plugins/kibana/server/lib/export/__tests__/collect_panels.js b/src/core_plugins/kibana/server/lib/export/__tests__/collect_panels.js index f48ddb1229b085..f15d6a088f9977 100644 --- a/src/core_plugins/kibana/server/lib/export/__tests__/collect_panels.js +++ b/src/core_plugins/kibana/server/lib/export/__tests__/collect_panels.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import * as collectIndexPatternsDep from '../collect_index_patterns'; import * as collectSearchSourcesDep from '../collect_search_sources'; @@ -9,7 +28,7 @@ describe('collectPanels(req, dashboard)', () => { let collectIndexPatternsStub; let dashboard; - const savedObjectsClient = { bulkGet: sinon.mock() }; + const savedObjectsClient = { bulkGet: sinon.stub() }; beforeEach(() => { dashboard = { @@ -36,7 +55,7 @@ describe('collectPanels(req, dashboard)', () => { afterEach(() => { collectSearchSourcesStub.restore(); collectIndexPatternsStub.restore(); - savedObjectsClient.bulkGet.reset(); + savedObjectsClient.bulkGet.resetHistory(); }); it('should request each panel in the panelJSON', async () => { diff --git a/src/core_plugins/kibana/server/lib/export/__tests__/collect_search_sources.js b/src/core_plugins/kibana/server/lib/export/__tests__/collect_search_sources.js index 22ecf8f3b50007..4f9de8a971b7c2 100644 --- a/src/core_plugins/kibana/server/lib/export/__tests__/collect_search_sources.js +++ b/src/core_plugins/kibana/server/lib/export/__tests__/collect_search_sources.js @@ -1,9 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import * as deps from '../collect_index_patterns'; import { collectSearchSources } from '../collect_search_sources'; import { expect } from 'chai'; describe('collectSearchSources(req, panels)', () => { - const savedObjectsClient = { bulkGet: sinon.mock() }; + const savedObjectsClient = { bulkGet: sinon.stub() }; let panels; let collectIndexPatternsStub; @@ -26,7 +45,7 @@ describe('collectSearchSources(req, panels)', () => { afterEach(() => { collectIndexPatternsStub.restore(); - savedObjectsClient.bulkGet.reset(); + savedObjectsClient.bulkGet.resetHistory(); }); it('should request all search sources', async () => { diff --git a/src/core_plugins/kibana/server/lib/export/__tests__/export_dashboards.js b/src/core_plugins/kibana/server/lib/export/__tests__/export_dashboards.js index 0b7990cebd2c96..04da5719f3634f 100644 --- a/src/core_plugins/kibana/server/lib/export/__tests__/export_dashboards.js +++ b/src/core_plugins/kibana/server/lib/export/__tests__/export_dashboards.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import * as deps from '../collect_dashboards'; import { exportDashboards } from '../export_dashboards'; import sinon from 'sinon'; diff --git a/src/core_plugins/kibana/server/lib/export/collect_dashboards.js b/src/core_plugins/kibana/server/lib/export/collect_dashboards.js index 9600f0157f449d..969c2add1364d3 100644 --- a/src/core_plugins/kibana/server/lib/export/collect_dashboards.js +++ b/src/core_plugins/kibana/server/lib/export/collect_dashboards.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { collectPanels } from './collect_panels'; export async function collectDashboards(savedObjectsClient, ids) { diff --git a/src/core_plugins/kibana/server/lib/export/collect_index_patterns.js b/src/core_plugins/kibana/server/lib/export/collect_index_patterns.js index b0a7688daa8899..1f1be4baf9ad28 100644 --- a/src/core_plugins/kibana/server/lib/export/collect_index_patterns.js +++ b/src/core_plugins/kibana/server/lib/export/collect_index_patterns.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export async function collectIndexPatterns(savedObjectsClient, panels) { const docs = panels.reduce((acc, panel) => { const { kibanaSavedObjectMeta, savedSearchId } = panel.attributes; diff --git a/src/core_plugins/kibana/server/lib/export/collect_panels.js b/src/core_plugins/kibana/server/lib/export/collect_panels.js index e53e1f7bdbb5cd..eba6e335818e30 100644 --- a/src/core_plugins/kibana/server/lib/export/collect_panels.js +++ b/src/core_plugins/kibana/server/lib/export/collect_panels.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { get } from 'lodash'; import { collectIndexPatterns } from './collect_index_patterns'; diff --git a/src/core_plugins/kibana/server/lib/export/collect_search_sources.js b/src/core_plugins/kibana/server/lib/export/collect_search_sources.js index c0804f233bcd7f..38471e9b6012c3 100644 --- a/src/core_plugins/kibana/server/lib/export/collect_search_sources.js +++ b/src/core_plugins/kibana/server/lib/export/collect_search_sources.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { collectIndexPatterns } from './collect_index_patterns'; export async function collectSearchSources(savedObjectsClient, panels) { diff --git a/src/core_plugins/kibana/server/lib/export/export_dashboards.js b/src/core_plugins/kibana/server/lib/export/export_dashboards.js index 2a2d22d43f98b1..ed61d2c83366af 100644 --- a/src/core_plugins/kibana/server/lib/export/export_dashboards.js +++ b/src/core_plugins/kibana/server/lib/export/export_dashboards.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { collectDashboards } from './collect_dashboards'; diff --git a/src/core_plugins/kibana/server/lib/handle_es_error.js b/src/core_plugins/kibana/server/lib/handle_es_error.js index dfa2179a12a409..3cbc886784fa76 100644 --- a/src/core_plugins/kibana/server/lib/handle_es_error.js +++ b/src/core_plugins/kibana/server/lib/handle_es_error.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Boom from 'boom'; import _ from 'lodash'; import { errors as esErrors } from 'elasticsearch'; diff --git a/src/core_plugins/kibana/server/lib/import/__tests__/import_dashboards.js b/src/core_plugins/kibana/server/lib/import/__tests__/import_dashboards.js index 5ce2dc2561738b..6fbcfd14a72a73 100644 --- a/src/core_plugins/kibana/server/lib/import/__tests__/import_dashboards.js +++ b/src/core_plugins/kibana/server/lib/import/__tests__/import_dashboards.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { importDashboards } from '../import_dashboards'; import sinon from 'sinon'; import { expect } from 'chai'; diff --git a/src/core_plugins/kibana/server/lib/import/import_dashboards.js b/src/core_plugins/kibana/server/lib/import/import_dashboards.js index 0f4d2e73db985b..0db3d2ff343380 100644 --- a/src/core_plugins/kibana/server/lib/import/import_dashboards.js +++ b/src/core_plugins/kibana/server/lib/import/import_dashboards.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { flatten } from 'lodash'; export async function importDashboards(req) { diff --git a/src/core_plugins/kibana/server/lib/manage_uuid.js b/src/core_plugins/kibana/server/lib/manage_uuid.js index 83bf4fd06d6d07..0c744ef3ac18b6 100644 --- a/src/core_plugins/kibana/server/lib/manage_uuid.js +++ b/src/core_plugins/kibana/server/lib/manage_uuid.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import uuid from 'uuid'; import Promise from 'bluebird'; import { join as pathJoin } from 'path'; diff --git a/src/core_plugins/kibana/server/lib/management/saved_objects/relationships.js b/src/core_plugins/kibana/server/lib/management/saved_objects/relationships.js new file mode 100644 index 00000000000000..55e28db2203fd5 --- /dev/null +++ b/src/core_plugins/kibana/server/lib/management/saved_objects/relationships.js @@ -0,0 +1,178 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +async function findDashboardRelationships(id, size, savedObjectsClient) { + const dashboard = await savedObjectsClient.get('dashboard', id); + const visualizations = []; + + // TODO: should we handle exceptions here or at the parent level? + const panelsJSON = JSON.parse(dashboard.attributes.panelsJSON); + if (panelsJSON) { + const visualizationIds = panelsJSON.map(panel => panel.id); + const visualizationResponse = await savedObjectsClient.bulkGet(visualizationIds.slice(0, size).map(id => ({ + id, + type: 'visualization', + }))); + + visualizations.push(...visualizationResponse.saved_objects.reduce((accum, object) => { + if (!object.error) { + accum.push({ + id: object.id, + title: object.attributes.title, + }); + } + return accum; + }, [])); + } + + return { visualizations }; +} + +async function findVisualizationRelationships(id, size, savedObjectsClient) { + const allDashboardsResponse = await savedObjectsClient.find({ + type: 'dashboard', + fields: ['title', 'panelsJSON'] + }); + + const dashboards = []; + for (const dashboard of allDashboardsResponse.saved_objects) { + if (dashboard.error) { + continue; + } + const panelsJSON = JSON.parse(dashboard.attributes.panelsJSON); + if (panelsJSON) { + for (const panel of panelsJSON) { + if (panel.type === 'visualization' && panel.id === id) { + dashboards.push({ + id: dashboard.id, + title: dashboard.attributes.title, + }); + } + } + } + + if (dashboards.length >= size) { + break; + } + } + + return { dashboards }; +} + +async function findSavedSearchRelationships(id, size, savedObjectsClient) { + const search = await savedObjectsClient.get('search', id); + + const searchSourceJSON = JSON.parse(search.attributes.kibanaSavedObjectMeta.searchSourceJSON); + + const indexPatterns = []; + try { + const indexPattern = await savedObjectsClient.get('index-pattern', searchSourceJSON.index); + indexPatterns.push({ id: indexPattern.id, title: indexPattern.attributes.title }); + } catch (err) { + // Do nothing + } + + const allVisualizationsResponse = await savedObjectsClient.find({ + type: 'visualization', + searchFields: ['savedSearchId'], + search: id, + fields: ['title'] + }); + + const visualizations = allVisualizationsResponse.saved_objects.reduce((accum, object) => { + if (!object.error) { + accum.push({ + id: object.id, + title: object.attributes.title, + }); + } + return accum; + }, []); + + return { visualizations, indexPatterns }; +} + +async function findIndexPatternRelationships(id, size, savedObjectsClient) { + const [allVisualizationsResponse, savedSearchResponse] = await Promise.all([ + savedObjectsClient.find({ + type: 'visualization', + searchFields: ['kibanaSavedObjectMeta.searchSourceJSON'], + search: '*', + fields: [`title`, `kibanaSavedObjectMeta.searchSourceJSON`], + }), + savedObjectsClient.find({ + type: 'search', + searchFields: ['kibanaSavedObjectMeta.searchSourceJSON'], + search: '*', + fields: [`title`, `kibanaSavedObjectMeta.searchSourceJSON`], + }), + ]); + + const visualizations = []; + for (const visualization of allVisualizationsResponse.saved_objects) { + if (visualization.error) { + continue; + } + const searchSourceJSON = JSON.parse(visualization.attributes.kibanaSavedObjectMeta.searchSourceJSON); + if (searchSourceJSON && searchSourceJSON.index === id) { + visualizations.push({ + id: visualization.id, + title: visualization.attributes.title, + }); + } + + if (visualizations.length >= size) { + break; + } + } + + const searches = []; + for (const search of savedSearchResponse.saved_objects) { + if (search.error) { + continue; + } + const searchSourceJSON = JSON.parse(search.attributes.kibanaSavedObjectMeta.searchSourceJSON); + if (searchSourceJSON && searchSourceJSON.index === id) { + searches.push({ + id: search.id, + title: search.attributes.title, + }); + } + + if (searches.length >= size) { + break; + } + } + + return { visualizations, searches }; +} + +export async function findRelationships(type, id, size, savedObjectsClient) { + switch (type) { + case 'dashboard': + return await findDashboardRelationships(id, size, savedObjectsClient); + case 'visualization': + return await findVisualizationRelationships(id, size, savedObjectsClient); + case 'search': + return await findSavedSearchRelationships(id, size, savedObjectsClient); + case 'index-pattern': + return await findIndexPatternRelationships(id, size, savedObjectsClient); + } + return {}; +} diff --git a/src/core_plugins/kibana/server/lib/system_api.js b/src/core_plugins/kibana/server/lib/system_api.js index e50ebf30354e73..24c901a3db0a48 100644 --- a/src/core_plugins/kibana/server/lib/system_api.js +++ b/src/core_plugins/kibana/server/lib/system_api.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const SYSTEM_API_HEADER_NAME = 'kbn-system-api'; /** diff --git a/src/core_plugins/kibana/server/routes/api/export/index.js b/src/core_plugins/kibana/server/routes/api/export/index.js index 5372c112000c26..832369c1f0f46f 100644 --- a/src/core_plugins/kibana/server/routes/api/export/index.js +++ b/src/core_plugins/kibana/server/routes/api/export/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { exportDashboards } from '../../../lib/export/export_dashboards'; import Boom from 'boom'; import Joi from 'joi'; diff --git a/src/core_plugins/kibana/server/routes/api/home/index.js b/src/core_plugins/kibana/server/routes/api/home/index.js index 154d9eea1a33ec..6a4303819f3e9c 100644 --- a/src/core_plugins/kibana/server/routes/api/home/index.js +++ b/src/core_plugins/kibana/server/routes/api/home/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { registerTutorials } from './register_tutorials'; export function homeApi(server) { diff --git a/src/core_plugins/kibana/server/routes/api/home/register_tutorials.js b/src/core_plugins/kibana/server/routes/api/home/register_tutorials.js index b22e135288f716..c7e0909631eaec 100644 --- a/src/core_plugins/kibana/server/routes/api/home/register_tutorials.js +++ b/src/core_plugins/kibana/server/routes/api/home/register_tutorials.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function registerTutorials(server) { server.route({ diff --git a/src/core_plugins/kibana/server/routes/api/import/index.js b/src/core_plugins/kibana/server/routes/api/import/index.js index bf8cfabb71fedb..945bd02059507d 100644 --- a/src/core_plugins/kibana/server/routes/api/import/index.js +++ b/src/core_plugins/kibana/server/routes/api/import/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Boom from 'boom'; import Joi from 'joi'; import { importDashboards } from '../../../lib/import/import_dashboards'; diff --git a/src/core_plugins/kibana/server/routes/api/management/index.js b/src/core_plugins/kibana/server/routes/api/management/index.js new file mode 100644 index 00000000000000..b06b4913bffa1a --- /dev/null +++ b/src/core_plugins/kibana/server/routes/api/management/index.js @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { registerRelationships } from './saved_objects/relationships'; +import { registerScrollForExportRoute, registerScrollForCountRoute } from './saved_objects/scroll'; + +export function managementApi(server) { + registerRelationships(server); + registerScrollForExportRoute(server); + registerScrollForCountRoute(server); +} diff --git a/src/core_plugins/kibana/server/routes/api/management/saved_objects/relationships.js b/src/core_plugins/kibana/server/routes/api/management/saved_objects/relationships.js new file mode 100644 index 00000000000000..6cead2f57f9362 --- /dev/null +++ b/src/core_plugins/kibana/server/routes/api/management/saved_objects/relationships.js @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Boom from 'boom'; +import Joi from 'joi'; +import { findRelationships } from '../../../../lib/management/saved_objects/relationships'; + +export function registerRelationships(server) { + server.route({ + path: '/api/kibana/management/saved_objects/relationships/{type}/{id}', + method: ['GET'], + config: { + validate: { + params: Joi.object().keys({ + type: Joi.string(), + id: Joi.string(), + }), + query: Joi.object().keys({ + size: Joi.number(), + }) + }, + }, + + handler: async (req, reply) => { + const type = req.params.type; + const id = req.params.id; + const size = req.query.size || 10; + + try { + const response = await findRelationships( + type, + id, + size, + req.getSavedObjectsClient(), + ); + + reply(response); + } + catch (err) { + reply(Boom.boomify(err, { statusCode: 500 })); + } + } + }); +} diff --git a/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js b/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js new file mode 100644 index 00000000000000..3cc51f2976ca18 --- /dev/null +++ b/src/core_plugins/kibana/server/routes/api/management/saved_objects/scroll.js @@ -0,0 +1,113 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Joi from 'joi'; + +async function findAll(savedObjectsClient, findOptions, page = 1, allObjects = []) { + const objects = await savedObjectsClient.find({ + ...findOptions, + page + }); + + allObjects.push(...objects.saved_objects); + if (allObjects.length < objects.total) { + return findAll(savedObjectsClient, findOptions, page + 1, allObjects); + } + + return allObjects; +} + +export function registerScrollForExportRoute(server) { + server.route({ + path: '/api/kibana/management/saved_objects/scroll/export', + method: ['POST'], + config: { + validate: { + payload: Joi.object().keys({ + typesToInclude: Joi.array().items(Joi.string()).required(), + }).required(), + }, + }, + + handler: async (req, reply) => { + const savedObjectsClient = req.getSavedObjectsClient(); + const objects = await findAll(savedObjectsClient, { + perPage: 1000, + typesToInclude: req.payload.typesToInclude + }); + const response = objects.map(hit => { + const type = hit.type; + return { + _id: hit.id, + _type: type, + _source: hit.attributes, + _meta: { + savedObjectVersion: 2 + } + }; + }); + + reply(response); + } + }); +} + +export function registerScrollForCountRoute(server) { + server.route({ + path: '/api/kibana/management/saved_objects/scroll/counts', + method: ['POST'], + config: { + validate: { + payload: Joi.object().keys({ + typesToInclude: Joi.array().items(Joi.string()).required(), + searchString: Joi.string() + }).required(), + }, + }, + + handler: async (req, reply) => { + const savedObjectsClient = req.getSavedObjectsClient(); + const findOptions = { + type: req.payload.typesToInclude, + perPage: 1000, + }; + + if (req.payload.searchString) { + findOptions.search = `${req.payload.searchString}*`; + findOptions.searchFields = ['title']; + } + + const objects = await findAll(savedObjectsClient, findOptions); + const counts = objects.reduce((accum, result) => { + const type = result.type; + accum[type] = accum[type] || 0; + accum[type]++; + return accum; + }, {}); + + for (const type of req.payload.typesToInclude) { + if (!counts[type]) { + counts[type] = 0; + } + } + + reply(counts); + } + }); +} diff --git a/src/core_plugins/kibana/server/routes/api/scripts/index.js b/src/core_plugins/kibana/server/routes/api/scripts/index.js index a24bb02b39ed47..441963b02f14fe 100644 --- a/src/core_plugins/kibana/server/routes/api/scripts/index.js +++ b/src/core_plugins/kibana/server/routes/api/scripts/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { registerLanguages } from './register_languages'; export function scriptsApi(server) { diff --git a/src/core_plugins/kibana/server/routes/api/scripts/register_languages.js b/src/core_plugins/kibana/server/routes/api/scripts/register_languages.js index f61be07bf6d589..f8520ea97b77a1 100644 --- a/src/core_plugins/kibana/server/routes/api/scripts/register_languages.js +++ b/src/core_plugins/kibana/server/routes/api/scripts/register_languages.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function registerLanguages(server) { server.route({ path: '/api/kibana/scripts/languages', diff --git a/src/core_plugins/kibana/server/routes/api/scroll_search/index.js b/src/core_plugins/kibana/server/routes/api/scroll_search/index.js index cfd366ab001dec..48301ded0523ec 100644 --- a/src/core_plugins/kibana/server/routes/api/scroll_search/index.js +++ b/src/core_plugins/kibana/server/routes/api/scroll_search/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import handleESError from '../../../lib/handle_es_error'; export function scrollSearchApi(server) { diff --git a/src/core_plugins/kibana/server/routes/api/search/count/register_count.js b/src/core_plugins/kibana/server/routes/api/search/count/register_count.js index 8b6be433db99b5..3a1fd9ee62e773 100644 --- a/src/core_plugins/kibana/server/routes/api/search/count/register_count.js +++ b/src/core_plugins/kibana/server/routes/api/search/count/register_count.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import handleESError from '../../../../lib/handle_es_error'; diff --git a/src/core_plugins/kibana/server/routes/api/search/index.js b/src/core_plugins/kibana/server/routes/api/search/index.js index 780b09340a71e5..32174f1f28e520 100644 --- a/src/core_plugins/kibana/server/routes/api/search/index.js +++ b/src/core_plugins/kibana/server/routes/api/search/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import registerCount from './count/register_count'; export function searchApi(server) { diff --git a/src/core_plugins/kibana/server/routes/api/suggestions/index.js b/src/core_plugins/kibana/server/routes/api/suggestions/index.js index 7bf2f5f10fda29..15110b192ee33c 100644 --- a/src/core_plugins/kibana/server/routes/api/suggestions/index.js +++ b/src/core_plugins/kibana/server/routes/api/suggestions/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { registerValueSuggestions } from './register_value_suggestions'; export function registerSuggestionsApi(server) { diff --git a/src/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js b/src/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js index 1083983e2f6eff..2823a5b0916e8c 100644 --- a/src/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js +++ b/src/core_plugins/kibana/server/routes/api/suggestions/register_value_suggestions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { get, map } from 'lodash'; import handleESError from '../../../lib/handle_es_error'; diff --git a/src/core_plugins/kibana/server/tutorials/apache_logs/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/apache_logs/elastic_cloud.js index 9a517988c9a9d2..dcb75354fb0ae3 100644 --- a/src/core_plugins/kibana/server/tutorials/apache_logs/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/apache_logs/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { FILEBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/filebeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/apache_logs/enable.js b/src/core_plugins/kibana/server/tutorials/apache_logs/enable.js index fe0ce9e4168347..35e35f8a78f07b 100644 --- a/src/core_plugins/kibana/server/tutorials/apache_logs/enable.js +++ b/src/core_plugins/kibana/server/tutorials/apache_logs/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the apache2 module', diff --git a/src/core_plugins/kibana/server/tutorials/apache_logs/index.js b/src/core_plugins/kibana/server/tutorials/apache_logs/index.js index eba15f49598716..674834c543c9c6 100644 --- a/src/core_plugins/kibana/server/tutorials/apache_logs/index.js +++ b/src/core_plugins/kibana/server/tutorials/apache_logs/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/apache_logs/on_prem.js b/src/core_plugins/kibana/server/tutorials/apache_logs/on_prem.js index 9ecaa557d24071..b07a6a38ab2f52 100644 --- a/src/core_plugins/kibana/server/tutorials/apache_logs/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/apache_logs/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/apache_logs/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/apache_logs/on_prem_elastic_cloud.js index 2266d33eccd1f1..b084122d77a374 100644 --- a/src/core_plugins/kibana/server/tutorials/apache_logs/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/apache_logs/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/apache_metrics/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/apache_metrics/elastic_cloud.js index 408ae869571e73..42c06cadc268bd 100644 --- a/src/core_plugins/kibana/server/tutorials/apache_metrics/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/apache_metrics/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/apache_metrics/enable.js b/src/core_plugins/kibana/server/tutorials/apache_metrics/enable.js index 9e18661701c7a4..1625a4709a363d 100644 --- a/src/core_plugins/kibana/server/tutorials/apache_metrics/enable.js +++ b/src/core_plugins/kibana/server/tutorials/apache_metrics/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the apache module', diff --git a/src/core_plugins/kibana/server/tutorials/apache_metrics/index.js b/src/core_plugins/kibana/server/tutorials/apache_metrics/index.js index 97e4d46d86f79b..bf15c0c88320e0 100644 --- a/src/core_plugins/kibana/server/tutorials/apache_metrics/index.js +++ b/src/core_plugins/kibana/server/tutorials/apache_metrics/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/apache_metrics/on_prem.js b/src/core_plugins/kibana/server/tutorials/apache_metrics/on_prem.js index 8a47014420ebe4..f5ce30acf70eef 100644 --- a/src/core_plugins/kibana/server/tutorials/apache_metrics/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/apache_metrics/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/apache_metrics/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/apache_metrics/on_prem_elastic_cloud.js index fe1cdbcde93916..bebe32e76117b2 100644 --- a/src/core_plugins/kibana/server/tutorials/apache_metrics/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/apache_metrics/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/apm/apm_client_instructions.js b/src/core_plugins/kibana/server/tutorials/apm/apm_client_instructions.js index c52c2306bc1c5d..7afa3a9bd08976 100644 --- a/src/core_plugins/kibana/server/tutorials/apm/apm_client_instructions.js +++ b/src/core_plugins/kibana/server/tutorials/apm/apm_client_instructions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* eslint-disable max-len */ export const NODE_CLIENT_INSTRUCTIONS = [ diff --git a/src/core_plugins/kibana/server/tutorials/apm/apm_server_instructions.js b/src/core_plugins/kibana/server/tutorials/apm/apm_server_instructions.js index c26644cc7e6240..679861ff43e815 100644 --- a/src/core_plugins/kibana/server/tutorials/apm/apm_server_instructions.js +++ b/src/core_plugins/kibana/server/tutorials/apm/apm_server_instructions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const EDIT_CONFIG = { title: 'Edit the configuration', textPre: diff --git a/src/core_plugins/kibana/server/tutorials/apm/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/apm/elastic_cloud.js index acd24f6e9573a6..6c43c8a80cc89f 100644 --- a/src/core_plugins/kibana/server/tutorials/apm/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/apm/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { diff --git a/src/core_plugins/kibana/server/tutorials/apm/index.js b/src/core_plugins/kibana/server/tutorials/apm/index.js index 2e4de77510598b..ca2661db97ee53 100644 --- a/src/core_plugins/kibana/server/tutorials/apm/index.js +++ b/src/core_plugins/kibana/server/tutorials/apm/index.js @@ -1,5 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; -import { ON_PREM_INSTRUCTIONS } from './on_prem'; +import { onPremInstructions } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; const apmIntro = 'Collect in-depth performance metrics and errors from inside your applications.'; @@ -42,7 +61,7 @@ export function apmSpecProvider(server) { ' [Learn more]({config.docs.base_url}guide/en/apm/get-started/{config.docs.version}/index.html).', euiIconType: 'apmApp', artifacts: artifacts, - onPrem: ON_PREM_INSTRUCTIONS, + onPrem: onPremInstructions(server), elasticCloud: ELASTIC_CLOUD_INSTRUCTIONS, previewImagePath: '/plugins/kibana/home/tutorial_resources/apm/apm.png', }; diff --git a/src/core_plugins/kibana/server/tutorials/apm/on_prem.js b/src/core_plugins/kibana/server/tutorials/apm/on_prem.js index 34f517aed67886..8e789e48c96601 100644 --- a/src/core_plugins/kibana/server/tutorials/apm/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/apm/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { WINDOWS_SERVER_INSTRUCTIONS, @@ -17,72 +36,122 @@ import { JS_CLIENT_INSTRUCTIONS, } from './apm_client_instructions'; -export const ON_PREM_INSTRUCTIONS = { - instructionSets: [ - { - title: 'APM Server', - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - DOWNLOAD_SERVER_OSX, - IMPORT_DASHBOARD_UNIX, - EDIT_CONFIG, - START_SERVER_UNIX, - ], - }, - { - id: INSTRUCTION_VARIANT.DEB, - instructions: [ - DOWNLOAD_SERVER_DEB, - IMPORT_DASHBOARD_UNIX, - EDIT_CONFIG, - START_SERVER_UNIX, - ], - }, - { - id: INSTRUCTION_VARIANT.RPM, - instructions: [ - DOWNLOAD_SERVER_RPM, - IMPORT_DASHBOARD_UNIX, - EDIT_CONFIG, - START_SERVER_UNIX, - ], - }, - { - id: INSTRUCTION_VARIANT.WINDOWS, - instructions: WINDOWS_SERVER_INSTRUCTIONS, - }, - ], - }, - { - title: 'APM Agents', - instructionVariants: [ - { - id: INSTRUCTION_VARIANT.NODE, - instructions: NODE_CLIENT_INSTRUCTIONS, - }, - { - id: INSTRUCTION_VARIANT.DJANGO, - instructions: DJANGO_CLIENT_INSTRUCTIONS, - }, - { - id: INSTRUCTION_VARIANT.FLASK, - instructions: FLASK_CLIENT_INSTRUCTIONS, - }, - { - id: INSTRUCTION_VARIANT.RAILS, - instructions: RAILS_CLIENT_INSTRUCTIONS, - }, - { - id: INSTRUCTION_VARIANT.RACK, - instructions: RACK_CLIENT_INSTRUCTIONS, +export function onPremInstructions(server) { + let apmIndexPattern = 'apm*'; + try { + apmIndexPattern = server.config().get('xpack.apm.indexPattern'); + } catch (error) { + // ignore error when config does not contain 'xpack.apm.indexPattern'. + // This is expected when APM plugin is not running. + } + + return { + instructionSets: [ + { + title: 'APM Server', + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + DOWNLOAD_SERVER_OSX, + IMPORT_DASHBOARD_UNIX, + EDIT_CONFIG, + START_SERVER_UNIX, + ], + }, + { + id: INSTRUCTION_VARIANT.DEB, + instructions: [ + DOWNLOAD_SERVER_DEB, + IMPORT_DASHBOARD_UNIX, + EDIT_CONFIG, + START_SERVER_UNIX, + ], + }, + { + id: INSTRUCTION_VARIANT.RPM, + instructions: [ + DOWNLOAD_SERVER_RPM, + IMPORT_DASHBOARD_UNIX, + EDIT_CONFIG, + START_SERVER_UNIX, + ], + }, + { + id: INSTRUCTION_VARIANT.WINDOWS, + instructions: WINDOWS_SERVER_INSTRUCTIONS, + }, + ], + statusCheck: { + title: 'APM Server status', + text: + 'Make sure APM Server is running before you start implementing the APM agents.', + btnLabel: 'Check APM Server status', + success: 'You have correctly setup APM-Server', + error: 'APM-Server has still not connected to Elasticsearch', + esHitsCheck: { + index: apmIndexPattern, + query: { + bool: { + filter: { + exists: { + field: 'listening', + }, + }, + }, + }, + }, }, - { - id: INSTRUCTION_VARIANT.JS, - instructions: JS_CLIENT_INSTRUCTIONS, + }, + { + title: 'APM Agents', + instructionVariants: [ + { + id: INSTRUCTION_VARIANT.NODE, + instructions: NODE_CLIENT_INSTRUCTIONS, + }, + { + id: INSTRUCTION_VARIANT.DJANGO, + instructions: DJANGO_CLIENT_INSTRUCTIONS, + }, + { + id: INSTRUCTION_VARIANT.FLASK, + instructions: FLASK_CLIENT_INSTRUCTIONS, + }, + { + id: INSTRUCTION_VARIANT.RAILS, + instructions: RAILS_CLIENT_INSTRUCTIONS, + }, + { + id: INSTRUCTION_VARIANT.RACK, + instructions: RACK_CLIENT_INSTRUCTIONS, + }, + { + id: INSTRUCTION_VARIANT.JS, + instructions: JS_CLIENT_INSTRUCTIONS, + }, + ], + statusCheck: { + title: 'Agent status', + text: + 'Make sure you application is running, and the agents are sending data', + btnLabel: 'Check agent status', + success: 'Data succesfully received from one or more agents', + error: `No data has been received from agents yet`, + esHitsCheck: { + index: apmIndexPattern, + query: { + bool: { + filter: { + exists: { + field: 'processor.name', + }, + }, + }, + }, + }, }, - ], - }, - ], -}; + }, + ], + }; +} diff --git a/src/core_plugins/kibana/server/tutorials/docker_metrics/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/docker_metrics/elastic_cloud.js index 408ae869571e73..42c06cadc268bd 100644 --- a/src/core_plugins/kibana/server/tutorials/docker_metrics/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/docker_metrics/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/docker_metrics/enable.js b/src/core_plugins/kibana/server/tutorials/docker_metrics/enable.js index 4fafad9e6bf1a8..8603822cbee8c8 100644 --- a/src/core_plugins/kibana/server/tutorials/docker_metrics/enable.js +++ b/src/core_plugins/kibana/server/tutorials/docker_metrics/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the docker module', diff --git a/src/core_plugins/kibana/server/tutorials/docker_metrics/index.js b/src/core_plugins/kibana/server/tutorials/docker_metrics/index.js index 539334f2ac6d7e..857fc250a30738 100644 --- a/src/core_plugins/kibana/server/tutorials/docker_metrics/index.js +++ b/src/core_plugins/kibana/server/tutorials/docker_metrics/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/docker_metrics/on_prem.js b/src/core_plugins/kibana/server/tutorials/docker_metrics/on_prem.js index 8a47014420ebe4..f5ce30acf70eef 100644 --- a/src/core_plugins/kibana/server/tutorials/docker_metrics/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/docker_metrics/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/docker_metrics/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/docker_metrics/on_prem_elastic_cloud.js index fe1cdbcde93916..bebe32e76117b2 100644 --- a/src/core_plugins/kibana/server/tutorials/docker_metrics/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/docker_metrics/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/elastic_cloud.js index 408ae869571e73..42c06cadc268bd 100644 --- a/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/enable.js b/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/enable.js index b906809be0f2ac..7b1bba62c43162 100644 --- a/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/enable.js +++ b/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the kubernetes module', diff --git a/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/index.js b/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/index.js index fe1325e4ee012c..811fce8ffe64fc 100644 --- a/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/index.js +++ b/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/on_prem.js b/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/on_prem.js index 8a47014420ebe4..f5ce30acf70eef 100644 --- a/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/on_prem_elastic_cloud.js index fe1cdbcde93916..bebe32e76117b2 100644 --- a/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/kubernetes_metrics/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/mysql_logs/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/mysql_logs/elastic_cloud.js index 9a517988c9a9d2..dcb75354fb0ae3 100644 --- a/src/core_plugins/kibana/server/tutorials/mysql_logs/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/mysql_logs/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { FILEBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/filebeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/mysql_logs/enable.js b/src/core_plugins/kibana/server/tutorials/mysql_logs/enable.js index a303c187175119..7c9bc244e3645b 100644 --- a/src/core_plugins/kibana/server/tutorials/mysql_logs/enable.js +++ b/src/core_plugins/kibana/server/tutorials/mysql_logs/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the mysql module', diff --git a/src/core_plugins/kibana/server/tutorials/mysql_logs/index.js b/src/core_plugins/kibana/server/tutorials/mysql_logs/index.js index 3c5f4328da53c1..8b5cef7078b7b1 100644 --- a/src/core_plugins/kibana/server/tutorials/mysql_logs/index.js +++ b/src/core_plugins/kibana/server/tutorials/mysql_logs/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/mysql_logs/on_prem.js b/src/core_plugins/kibana/server/tutorials/mysql_logs/on_prem.js index e280230d7b78ef..14f83fb20795f9 100644 --- a/src/core_plugins/kibana/server/tutorials/mysql_logs/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/mysql_logs/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/mysql_logs/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/mysql_logs/on_prem_elastic_cloud.js index 2266d33eccd1f1..b084122d77a374 100644 --- a/src/core_plugins/kibana/server/tutorials/mysql_logs/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/mysql_logs/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/mysql_metrics/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/mysql_metrics/elastic_cloud.js index 408ae869571e73..42c06cadc268bd 100644 --- a/src/core_plugins/kibana/server/tutorials/mysql_metrics/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/mysql_metrics/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/mysql_metrics/enable.js b/src/core_plugins/kibana/server/tutorials/mysql_metrics/enable.js index 815f68f7949109..9cab49f50c201b 100644 --- a/src/core_plugins/kibana/server/tutorials/mysql_metrics/enable.js +++ b/src/core_plugins/kibana/server/tutorials/mysql_metrics/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the mysql module', diff --git a/src/core_plugins/kibana/server/tutorials/mysql_metrics/index.js b/src/core_plugins/kibana/server/tutorials/mysql_metrics/index.js index a21f1014d16176..3c37f85adc6eaf 100644 --- a/src/core_plugins/kibana/server/tutorials/mysql_metrics/index.js +++ b/src/core_plugins/kibana/server/tutorials/mysql_metrics/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/mysql_metrics/on_prem.js b/src/core_plugins/kibana/server/tutorials/mysql_metrics/on_prem.js index 8a47014420ebe4..f5ce30acf70eef 100644 --- a/src/core_plugins/kibana/server/tutorials/mysql_metrics/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/mysql_metrics/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/mysql_metrics/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/mysql_metrics/on_prem_elastic_cloud.js index fe1cdbcde93916..bebe32e76117b2 100644 --- a/src/core_plugins/kibana/server/tutorials/mysql_metrics/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/mysql_metrics/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/netflow/common_instructions.js b/src/core_plugins/kibana/server/tutorials/netflow/common_instructions.js index fa17fff0078246..2a7364c0529729 100644 --- a/src/core_plugins/kibana/server/tutorials/netflow/common_instructions.js +++ b/src/core_plugins/kibana/server/tutorials/netflow/common_instructions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const COMMON_NETFLOW_INSTRUCTIONS = { CONFIG: { ON_PREM: { diff --git a/src/core_plugins/kibana/server/tutorials/netflow/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/netflow/elastic_cloud.js index b27ec3a021713f..21e396bb9db280 100644 --- a/src/core_plugins/kibana/server/tutorials/netflow/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/netflow/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { LOGSTASH_INSTRUCTIONS } from '../../../common/tutorials/logstash_instructions'; import { COMMON_NETFLOW_INSTRUCTIONS } from './common_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/netflow/index.js b/src/core_plugins/kibana/server/tutorials/netflow/index.js index a346a986f74231..e634282acc5650 100644 --- a/src/core_plugins/kibana/server/tutorials/netflow/index.js +++ b/src/core_plugins/kibana/server/tutorials/netflow/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/netflow/on_prem.js b/src/core_plugins/kibana/server/tutorials/netflow/on_prem.js index c398555f9efb90..5b0ecbbaac2c70 100644 --- a/src/core_plugins/kibana/server/tutorials/netflow/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/netflow/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { LOGSTASH_INSTRUCTIONS } from '../../../common/tutorials/logstash_instructions'; import { COMMON_NETFLOW_INSTRUCTIONS } from './common_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/netflow/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/netflow/on_prem_elastic_cloud.js index 957825be96c3a5..0e5cb74064f804 100644 --- a/src/core_plugins/kibana/server/tutorials/netflow/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/netflow/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { LOGSTASH_INSTRUCTIONS } from '../../../common/tutorials/logstash_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/nginx_logs/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/nginx_logs/elastic_cloud.js index 9a517988c9a9d2..dcb75354fb0ae3 100644 --- a/src/core_plugins/kibana/server/tutorials/nginx_logs/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/nginx_logs/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { FILEBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/filebeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/nginx_logs/enable.js b/src/core_plugins/kibana/server/tutorials/nginx_logs/enable.js index 70be5bc520555e..ac3175138b16a1 100644 --- a/src/core_plugins/kibana/server/tutorials/nginx_logs/enable.js +++ b/src/core_plugins/kibana/server/tutorials/nginx_logs/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the nginx module', diff --git a/src/core_plugins/kibana/server/tutorials/nginx_logs/index.js b/src/core_plugins/kibana/server/tutorials/nginx_logs/index.js index bf99369a9f908e..a30e97917fb032 100644 --- a/src/core_plugins/kibana/server/tutorials/nginx_logs/index.js +++ b/src/core_plugins/kibana/server/tutorials/nginx_logs/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/nginx_logs/on_prem.js b/src/core_plugins/kibana/server/tutorials/nginx_logs/on_prem.js index 9ecaa557d24071..b07a6a38ab2f52 100644 --- a/src/core_plugins/kibana/server/tutorials/nginx_logs/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/nginx_logs/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/nginx_logs/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/nginx_logs/on_prem_elastic_cloud.js index 2266d33eccd1f1..b084122d77a374 100644 --- a/src/core_plugins/kibana/server/tutorials/nginx_logs/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/nginx_logs/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/nginx_metrics/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/nginx_metrics/elastic_cloud.js index 408ae869571e73..42c06cadc268bd 100644 --- a/src/core_plugins/kibana/server/tutorials/nginx_metrics/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/nginx_metrics/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/nginx_metrics/enable.js b/src/core_plugins/kibana/server/tutorials/nginx_metrics/enable.js index 8f30486c54c90c..89eed8a927c107 100644 --- a/src/core_plugins/kibana/server/tutorials/nginx_metrics/enable.js +++ b/src/core_plugins/kibana/server/tutorials/nginx_metrics/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the nginx module', diff --git a/src/core_plugins/kibana/server/tutorials/nginx_metrics/index.js b/src/core_plugins/kibana/server/tutorials/nginx_metrics/index.js index 9eeb1e64cead22..ed68420de67f63 100644 --- a/src/core_plugins/kibana/server/tutorials/nginx_metrics/index.js +++ b/src/core_plugins/kibana/server/tutorials/nginx_metrics/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/nginx_metrics/on_prem.js b/src/core_plugins/kibana/server/tutorials/nginx_metrics/on_prem.js index 8a47014420ebe4..f5ce30acf70eef 100644 --- a/src/core_plugins/kibana/server/tutorials/nginx_metrics/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/nginx_metrics/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/nginx_metrics/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/nginx_metrics/on_prem_elastic_cloud.js index fe1cdbcde93916..bebe32e76117b2 100644 --- a/src/core_plugins/kibana/server/tutorials/nginx_metrics/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/nginx_metrics/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/redis_logs/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/redis_logs/elastic_cloud.js index 9a517988c9a9d2..dcb75354fb0ae3 100644 --- a/src/core_plugins/kibana/server/tutorials/redis_logs/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/redis_logs/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { FILEBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/filebeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/redis_logs/enable.js b/src/core_plugins/kibana/server/tutorials/redis_logs/enable.js index eae7e0666b9498..45c39b0161a7e3 100644 --- a/src/core_plugins/kibana/server/tutorials/redis_logs/enable.js +++ b/src/core_plugins/kibana/server/tutorials/redis_logs/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the redis module', diff --git a/src/core_plugins/kibana/server/tutorials/redis_logs/index.js b/src/core_plugins/kibana/server/tutorials/redis_logs/index.js index 39e7d00b41eda2..129d4cd7422ee1 100644 --- a/src/core_plugins/kibana/server/tutorials/redis_logs/index.js +++ b/src/core_plugins/kibana/server/tutorials/redis_logs/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/redis_logs/on_prem.js b/src/core_plugins/kibana/server/tutorials/redis_logs/on_prem.js index e280230d7b78ef..14f83fb20795f9 100644 --- a/src/core_plugins/kibana/server/tutorials/redis_logs/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/redis_logs/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/redis_logs/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/redis_logs/on_prem_elastic_cloud.js index 2266d33eccd1f1..b084122d77a374 100644 --- a/src/core_plugins/kibana/server/tutorials/redis_logs/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/redis_logs/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/redis_metrics/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/redis_metrics/elastic_cloud.js index 408ae869571e73..42c06cadc268bd 100644 --- a/src/core_plugins/kibana/server/tutorials/redis_metrics/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/redis_metrics/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/redis_metrics/enable.js b/src/core_plugins/kibana/server/tutorials/redis_metrics/enable.js index 74a3619d28058b..eef14be79a57a5 100644 --- a/src/core_plugins/kibana/server/tutorials/redis_metrics/enable.js +++ b/src/core_plugins/kibana/server/tutorials/redis_metrics/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the redis module', diff --git a/src/core_plugins/kibana/server/tutorials/redis_metrics/index.js b/src/core_plugins/kibana/server/tutorials/redis_metrics/index.js index 9282620c447438..7e210985b8be0e 100644 --- a/src/core_plugins/kibana/server/tutorials/redis_metrics/index.js +++ b/src/core_plugins/kibana/server/tutorials/redis_metrics/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/redis_metrics/on_prem.js b/src/core_plugins/kibana/server/tutorials/redis_metrics/on_prem.js index 8a47014420ebe4..f5ce30acf70eef 100644 --- a/src/core_plugins/kibana/server/tutorials/redis_metrics/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/redis_metrics/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/redis_metrics/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/redis_metrics/on_prem_elastic_cloud.js index fe1cdbcde93916..bebe32e76117b2 100644 --- a/src/core_plugins/kibana/server/tutorials/redis_metrics/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/redis_metrics/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/register.js b/src/core_plugins/kibana/server/tutorials/register.js index ca4ed62b1ba6ec..ba1db6fa4a438a 100644 --- a/src/core_plugins/kibana/server/tutorials/register.js +++ b/src/core_plugins/kibana/server/tutorials/register.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { systemLogsSpecProvider } from './system_logs'; import { systemMetricsSpecProvider } from './system_metrics'; import { apacheLogsSpecProvider } from './apache_logs'; diff --git a/src/core_plugins/kibana/server/tutorials/system_logs/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/system_logs/elastic_cloud.js index e3937f9bac5433..df06fe97d72cef 100644 --- a/src/core_plugins/kibana/server/tutorials/system_logs/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/system_logs/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { FILEBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/filebeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/system_logs/enable.js b/src/core_plugins/kibana/server/tutorials/system_logs/enable.js index 32ed797e763672..54ada7ca81fb2e 100644 --- a/src/core_plugins/kibana/server/tutorials/system_logs/enable.js +++ b/src/core_plugins/kibana/server/tutorials/system_logs/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the system module', diff --git a/src/core_plugins/kibana/server/tutorials/system_logs/index.js b/src/core_plugins/kibana/server/tutorials/system_logs/index.js index 09e86ee6a73e2a..a8086187c21c0d 100644 --- a/src/core_plugins/kibana/server/tutorials/system_logs/index.js +++ b/src/core_plugins/kibana/server/tutorials/system_logs/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/system_logs/on_prem.js b/src/core_plugins/kibana/server/tutorials/system_logs/on_prem.js index fbaa397343ae8a..4fd4514702f3c6 100644 --- a/src/core_plugins/kibana/server/tutorials/system_logs/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/system_logs/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/system_logs/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/system_logs/on_prem_elastic_cloud.js index b8c57633b1f671..f0e825c53d4278 100644 --- a/src/core_plugins/kibana/server/tutorials/system_logs/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/system_logs/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { FILEBEAT_INSTRUCTIONS } from '../../../common/tutorials/filebeat_instructions'; import { diff --git a/src/core_plugins/kibana/server/tutorials/system_metrics/elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/system_metrics/elastic_cloud.js index 408ae869571e73..42c06cadc268bd 100644 --- a/src/core_plugins/kibana/server/tutorials/system_metrics/elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/system_metrics/elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { METRICBEAT_CLOUD_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_cloud_instructions'; diff --git a/src/core_plugins/kibana/server/tutorials/system_metrics/enable.js b/src/core_plugins/kibana/server/tutorials/system_metrics/enable.js index f81af30a80ef74..5a9e85db4b7336 100644 --- a/src/core_plugins/kibana/server/tutorials/system_metrics/enable.js +++ b/src/core_plugins/kibana/server/tutorials/system_metrics/enable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const ENABLE_INSTRUCTIONS = { OSX: { title: 'Enable and configure the system module', diff --git a/src/core_plugins/kibana/server/tutorials/system_metrics/index.js b/src/core_plugins/kibana/server/tutorials/system_metrics/index.js index 2cff15dcd8ae01..6adafa65ef0b60 100644 --- a/src/core_plugins/kibana/server/tutorials/system_metrics/index.js +++ b/src/core_plugins/kibana/server/tutorials/system_metrics/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; import { ON_PREM_INSTRUCTIONS } from './on_prem'; import { ELASTIC_CLOUD_INSTRUCTIONS } from './elastic_cloud'; diff --git a/src/core_plugins/kibana/server/tutorials/system_metrics/on_prem.js b/src/core_plugins/kibana/server/tutorials/system_metrics/on_prem.js index 8a47014420ebe4..f5ce30acf70eef 100644 --- a/src/core_plugins/kibana/server/tutorials/system_metrics/on_prem.js +++ b/src/core_plugins/kibana/server/tutorials/system_metrics/on_prem.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { ENABLE_INSTRUCTIONS } from './enable'; diff --git a/src/core_plugins/kibana/server/tutorials/system_metrics/on_prem_elastic_cloud.js b/src/core_plugins/kibana/server/tutorials/system_metrics/on_prem_elastic_cloud.js index fe1cdbcde93916..bebe32e76117b2 100644 --- a/src/core_plugins/kibana/server/tutorials/system_metrics/on_prem_elastic_cloud.js +++ b/src/core_plugins/kibana/server/tutorials/system_metrics/on_prem_elastic_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { INSTRUCTION_VARIANT } from '../../../common/tutorials/instruction_variant'; import { METRICBEAT_INSTRUCTIONS } from '../../../common/tutorials/metricbeat_instructions'; import { diff --git a/src/core_plugins/kibana/ui_setting_defaults.js b/src/core_plugins/kibana/ui_setting_defaults.js index 88ba519b65137d..3056d072b48b73 100644 --- a/src/core_plugins/kibana/ui_setting_defaults.js +++ b/src/core_plugins/kibana/ui_setting_defaults.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import moment from 'moment-timezone'; import numeralLanguages from '@elastic/numeral/languages'; @@ -14,37 +33,46 @@ export function getUiSettingDefaults() { readonly: true }, 'query:queryString:options': { - value: '{ "analyze_wildcard": true, "default_field": "*" }', + name: 'Query string options', + value: '{ "analyze_wildcard": true }', description: 'Options for the lucene query string parser', type: 'json' }, 'query:allowLeadingWildcards': { + name: 'Allow leading wildcards in query', value: true, description: `When set, * is allowed as the first character in a query clause. Currently only applies when experimental query features are enabled in the query bar. To disallow leading wildcards in basic lucene queries, use query:queryString:options`, }, 'search:queryLanguage': { + name: 'Query language', value: 'lucene', - description: 'Query language used by the query bar. Kuery is an experimental new language built specifically for Kibana.', + description: `Query language used by the query bar. Kuery is an experimental new language built specifically for Kibana.`, type: 'select', options: ['lucene', 'kuery'] }, 'sort:options': { + name: 'Sort options', value: '{ "unmapped_type": "boolean" }', - description: 'Options for the Elasticsearch sort parameter', + description: `Options for the Elasticsearch sort parameter`, type: 'json' }, 'dateFormat': { + name: 'Date format', value: 'MMMM Do YYYY, HH:mm:ss.SSS', - description: 'When displaying a pretty formatted date, use this format', + description: `When displaying a pretty formatted date, use this format`, }, 'dateFormat:tz': { + name: 'Timezone for date formatting', value: 'Browser', - description: 'Which timezone should be used. "Browser" will use the timezone detected by your browser.', + description: `Which timezone should be used. "Browser" will use the timezone detected by your browser.`, type: 'select', options: ['Browser', ...moment.tz.names()] }, 'dateFormat:scaled': { + name: 'Scaled date format', type: 'json', value: `[ @@ -56,112 +84,139 @@ export function getUiSettingDefaults() { ["P1YT", "YYYY"] ]`, description: ( - 'Values that define the format used in situations where timebased' + - ' data is rendered in order, and formatted timestamps should adapt to the' + - ' interval between measurements. Keys are' + - ' ' + - 'ISO8601 intervals.' + `Values that define the format used in situations where time-based + data is rendered in order, and formatted timestamps should adapt to the + interval between measurements. Keys are + + ISO8601 intervals.` ) }, 'dateFormat:dow': { + name: 'Day of week', value: defaultWeekday, - description: 'What day should weeks start on?', + description: `What day should weeks start on?`, type: 'select', options: weekdays }, 'defaultIndex': { + name: 'Default index', value: null, - description: 'The index to access if no index is set', + description: `The index to access if no index is set`, }, 'defaultColumns': { + name: 'Default columns', value: ['_source'], - description: 'Columns displayed by default in the Discovery tab', + description: `Columns displayed by default in the Discovery tab`, + category: ['discover'], }, 'metaFields': { + name: 'Meta fields', value: ['_source', '_id', '_type', '_index', '_score'], - description: 'Fields that exist outside of _source to merge into our document when displaying it', + description: `Fields that exist outside of _source to merge into our document when displaying it`, }, 'discover:sampleSize': { + name: 'Number of rows', value: 500, - description: 'The number of rows to show in the table', + description: `The number of rows to show in the table`, + category: ['discover'], }, 'discover:aggs:terms:size': { + name: 'Number of terms', value: 20, type: 'number', - description: 'Determines how many terms will be visualized when clicking the "visualize" ' + - 'button, in the field drop downs, in the discover sidebar.' + description: `Determines how many terms will be visualized when clicking the "visualize" + button, in the field drop downs, in the discover sidebar.`, + category: ['discover'], }, 'discover:sort:defaultOrder': { + name: 'Default sort direction', value: 'desc', options: ['desc', 'asc'], type: 'select', - description: 'Controls the default sort direction for time based index patterns in the Discover app.', + description: `Controls the default sort direction for time based index patterns in the Discover app.`, + category: ['discover'], }, 'doc_table:highlight': { + name: 'Highlight results', value: true, - description: 'Highlight results in Discover and Saved Searches Dashboard.' + - 'Highlighting makes requests slow when working on big documents.', + description: `Highlight results in Discover and Saved Searches Dashboard. + Highlighting makes requests slow when working on big documents.`, + category: ['discover'], }, 'courier:maxSegmentCount': { + name: 'Maximum segment count', value: 30, - description: 'Requests in discover are split into segments to prevent massive requests from being sent to ' + - 'elasticsearch. This setting attempts to prevent the list of segments from getting too long, which might ' + - 'cause requests to take much longer to process' + description: `Requests in discover are split into segments to prevent massive requests from being sent to + elasticsearch. This setting attempts to prevent the list of segments from getting too long, which might + cause requests to take much longer to process.`, + category: ['search'], }, 'courier:ignoreFilterIfFieldNotInIndex': { + name: 'Ignore filter(s)', value: false, - description: 'This configuration enhances support for dashboards containing visualizations accessing dissimilar indexes. ' + - 'When set to false, all filters are applied to all visualizations. ' + - 'When set to true, filter(s) will be ignored for a visualization ' + - 'when the visualization\'s index does not contain the filtering field.' + description: `This configuration enhances support for dashboards containing visualizations accessing dissimilar indexes. + When set to false, all filters are applied to all visualizations. + When set to true, filter(s) will be ignored for a visualization + when the visualization's index does not contain the filtering field.`, + category: ['search'], }, 'courier:setRequestPreference': { + name: 'Request preference', value: 'sessionId', options: ['sessionId', 'custom', 'none'], type: 'select', - description: 'Allows you to set which shards handle your search requests. ' + - '
    ' + - '
  • sessionId: restricts operations to execute all search requests on the same shards. ' + - 'This has the benefit of reusing shard caches across requests. ' + - '
  • custom: allows you to define a your own preference. ' + - 'Use courier:customRequestPreference to customize your preference value. ' + - '
  • none: means do not set a preference. ' + - 'This might provide better performance because requests can be spread across all shard copies. ' + - 'However, results might be inconsistent because different shards might be in different refresh states.' + - '
' + description: `Allows you to set which shards handle your search requests. +
    +
  • sessionId: restricts operations to execute all search requests on the same shards. + This has the benefit of reusing shard caches across requests.
  • +
  • custom: allows you to define a your own preference. + Use courier:customRequestPreference to customize your preference value.
  • +
  • none: means do not set a preference. + This might provide better performance because requests can be spread across all shard copies. + However, results might be inconsistent because different shards might be in different refresh states.
  • +
`, + category: ['search'], }, 'courier:customRequestPreference': { + name: 'Custom request preference', value: '_local', type: 'string', - description: 'Request Preference ' + - ' used when courier:setRequestPreference is set to "custom".' + description: `Request Preference + used when courier:setRequestPreference is set to "custom".`, + category: ['search'], }, 'fields:popularLimit': { + name: 'Popular fields limit', value: 10, - description: 'The top N most popular fields to show', + description: `The top N most popular fields to show`, }, 'histogram:barTarget': { + name: 'Target bars', value: 50, - description: 'Attempt to generate around this many bars when using "auto" interval in date histograms', + description: `Attempt to generate around this many bars when using "auto" interval in date histograms`, }, 'histogram:maxBars': { + name: 'Maximum bars', value: 100, - description: 'Never show more than this many bars in date histograms, scale values if needed', + description: `Never show more than this many bars in date histograms, scale values if needed`, }, 'visualize:enableLabs': { + name: 'Enable labs', value: true, - description: 'Enable lab visualizations in Visualize.' + description: `Enable lab visualizations in Visualize.`, + category: ['visualization'], }, 'visualization:tileMap:maxPrecision': { + name: 'Maximum tile map precision', value: 7, - description: 'The maximum geoHash precision displayed on tile maps: 7 is high, 10 is very high, ' + - '12 is the max. ' + - '' + - 'Explanation of cell dimensions', + description: `The maximum geoHash precision displayed on tile maps: 7 is high, 10 is very high, 12 is the max. + Explanation of cell dimensions`, + category: ['visualization'], }, 'visualization:tileMap:WMSdefaults': { + name: 'Default WMS properties', value: JSON.stringify({ enabled: false, url: undefined, @@ -175,62 +230,79 @@ export function getUiSettingDefaults() { } }, null, 2), type: 'json', - description: 'Default properties for the WMS map server support in the coordinate map' + description: `Default properties for the WMS map server support in the coordinate map`, + category: ['visualization'], }, 'visualization:regionmap:showWarnings': { + name: 'Show region map warning', value: true, - description: 'Whether the region map show a warning when terms cannot be joined to a shape on the map.' + description: `Whether the region map shows a warning when terms cannot be joined to a shape on the map.`, + category: ['visualization'], }, 'visualization:colorMapping': { - type: 'json', + name: 'Color mapping', value: JSON.stringify({ Count: '#00A69B' }), - description: 'Maps values to specified colors within visualizations' + type: 'json', + description: `Maps values to specified colors within visualizations`, + category: ['visualization'], }, 'visualization:loadingDelay': { + name: 'Loading delay', value: '2s', - description: 'Time to wait before dimming visualizations during query' + description: `Time to wait before dimming visualizations during query`, + category: ['visualization'], }, 'visualization:dimmingOpacity': { - type: 'number', + name: 'Dimming opacity', value: 0.5, - description: 'The opacity of the chart items that are dimmed when highlighting another element of the chart. ' + - 'The lower this number, the more the highlighted element will stand out.' + - 'This must be a number between 0 and 1.' + type: 'number', + description: `The opacity of the chart items that are dimmed when highlighting another element of the chart. + The lower this number, the more the highlighted element will stand out. + This must be a number between 0 and 1.`, + category: ['visualization'], }, 'csv:separator': { + name: 'CSV separator', value: ',', - description: 'Separate exported values with this string', + description: `Separate exported values with this string`, }, 'csv:quoteValues': { + name: 'Quote CSV values', value: true, - description: 'Should values be quoted in csv exports?', + description: `Should values be quoted in csv exports?`, }, 'history:limit': { + name: 'History limit', value: 10, - description: 'In fields that have history (e.g. query inputs), show this many recent values', + description: `In fields that have history (e.g. query inputs), show this many recent values`, }, 'shortDots:enable': { + name: 'Shorten fields', value: false, - description: 'Shorten long fields, for example, instead of foo.bar.baz, show f.b.baz', + description: `Shorten long fields, for example, instead of foo.bar.baz, show f.b.baz`, }, 'truncate:maxHeight': { + name: 'Maximum table cell height', value: 115, - description: 'The maximum height that a cell in a table should occupy. Set to 0 to disable truncation' + description: `The maximum height that a cell in a table should occupy. Set to 0 to disable truncation`, }, 'indexPattern:fieldMapping:lookBack': { + name: 'Recent matching patterns', value: 5, - description: 'For index patterns containing timestamps in their names, look for this many recent matching ' + - 'patterns from which to query the field mapping' + description: `For index patterns containing timestamps in their names, look for this many recent matching + patterns from which to query the field mapping` }, 'indexPatterns:warnAboutUnsupportedTimePatterns': { + name: 'Time pattern warning', value: false, - description: 'When an index pattern is using the now unsupported "time pattern" format, a warning will ' + - 'be displayed once per session that is using this pattern. Set this to false to disable that warning.' + description: `When an index pattern is using the now unsupported "time pattern" format, a warning will + be displayed once per session that is using this pattern. Set this to false to disable that warning.` }, 'format:defaultTypeMap': { - type: 'json', + name: 'Field type format name', value: `{ "ip": { "id": "ip", "params": {} }, @@ -240,67 +312,77 @@ export function getUiSettingDefaults() { "_source": { "id": "_source", "params": {} }, "_default_": { "id": "string", "params": {} } }`, - description: 'Map of the format name to use by default for each field type. ' + - '"_default_" is used if the field type is not mentioned explicitly' + type: 'json', + description: `Map of the format name to use by default for each field type. + "_default_" is used if the field type is not mentioned explicitly` }, 'format:number:defaultPattern': { - type: 'string', + name: 'Number format', value: '0,0.[000]', - description: 'Default numeral format for the "number" format' + type: 'string', + description: `Default numeral format for the "number" format` }, 'format:bytes:defaultPattern': { - type: 'string', + name: 'Bytes format', value: '0,0.[000]b', - description: 'Default numeral format for the "bytes" format' + type: 'string', + description: `Default numeral format for the "bytes" format` }, 'format:percent:defaultPattern': { - type: 'string', + name: 'Percent format', value: '0,0.[000]%', - description: 'Default numeral format for the "percent" format' + type: 'string', + description: `Default numeral format for the "percent" format` }, 'format:currency:defaultPattern': { - type: 'string', + name: 'Currency format', value: '($0,0.[00])', - description: 'Default numeral format for the "currency" format' + type: 'string', + description: `Default numeral format for the "currency" format` }, 'format:number:defaultLocale': { + name: 'Formatting locale', value: 'en', type: 'select', options: numeralLanguageIds, - description: 'numeral language' + description: `Numeral language locale` }, 'savedObjects:perPage': { + name: 'Objects per page', + value: 20, type: 'number', - value: 5, - description: 'Number of objects to show per page in the load dialog' + description: `Number of objects to show per page in the load dialog` }, 'savedObjects:listingLimit': { + name: 'Objects listing limit', type: 'number', value: 1000, - description: 'Number of objects to fetch for the listing pages' + description: `Number of objects to fetch for the listing pages` }, 'timepicker:timeDefaults': { - type: 'json', + name: 'Time picker defaults', value: `{ "from": "now-15m", "to": "now", "mode": "quick" }`, - description: 'The timefilter selection to use when Kibana is started without one' + type: 'json', + description: `The timefilter selection to use when Kibana is started without one` }, 'timepicker:refreshIntervalDefaults': { - type: 'json', + name: 'Time picker refresh interval', value: `{ "display": "Off", "pause": false, "value": 0 }`, - description: 'The timefilter\'s default refresh interval' + type: 'json', + description: `The timefilter's default refresh interval` }, 'timepicker:quickRanges': { - type: 'json', + name: 'Time picker quick ranges', value: JSON.stringify([ { from: 'now/d', to: 'now/d', display: 'Today', section: 0 }, { from: 'now/w', to: 'now/w', display: 'This week', section: 0 }, @@ -328,79 +410,106 @@ export function getUiSettingDefaults() { { from: 'now-5y', to: 'now', display: 'Last 5 years', section: 2 }, ], null, 2), - description: 'The list of ranges to show in the Quick section of the time picker. ' + - 'This should be an array of objects, with each object containing "from", "to" (see ' + - 'accepted formats' + - '), "display" (the title to be displayed), and "section" (which column to put the option in).' + type: 'json', + description: `The list of ranges to show in the Quick section of the time picker. + This should be an array of objects, with each object containing "from", "to" (see + accepted formats), + "display" (the title to be displayed), and "section" (which column to put the option in).` }, 'dashboard:defaultDarkTheme': { + name: 'Dark theme', value: false, - description: 'New dashboards use dark theme by default' + description: `New dashboards use dark theme by default`, + category: ['dashboard'], }, 'filters:pinnedByDefault': { + name: 'Pin filters by default', value: false, - description: 'Whether the filters should have a global state (be pinned) by default' + description: `Whether the filters should have a global state (be pinned) by default` }, 'filterEditor:suggestValues': { + name: 'Filter editor suggest values', value: true, - description: 'Set this property to false to prevent the filter editor from suggesting values for fields.' + description: `Set this property to false to prevent the filter editor from suggesting values for fields.` }, 'notifications:banner': { + name: 'Custom banner notification', + value: '', type: 'markdown', - description: 'A custom banner intended for temporary notices to all users. Markdown supported.', - value: '' + description: `A custom banner intended for temporary notices to all users. + Markdown supported.`, + category: ['notifications'], }, 'notifications:lifetime:banner': { + name: 'Banner notification lifetime', value: 3000000, - description: 'The time in milliseconds which a banner notification ' + - 'will be displayed on-screen for. Setting to Infinity will disable the countdown.', + description: `The time in milliseconds which a banner notification + will be displayed on-screen for. Setting to Infinity will disable the countdown.`, type: 'number', + category: ['notifications'], }, 'notifications:lifetime:error': { + name: 'Error notification lifetime', value: 300000, - description: 'The time in milliseconds which an error notification ' + - 'will be displayed on-screen for. Setting to Infinity will disable.', + description: `The time in milliseconds which an error notification + 'will be displayed on-screen for. Setting to Infinity will disable.`, type: 'number', + category: ['notifications'], }, 'notifications:lifetime:warning': { + name: 'Warning notification lifetime', value: 10000, - description: 'The time in milliseconds which a warning notification ' + - 'will be displayed on-screen for. Setting to Infinity will disable.', + description: `The time in milliseconds which a warning notification + 'will be displayed on-screen for. Setting to Infinity will disable.`, type: 'number', + category: ['notifications'], }, 'notifications:lifetime:info': { + name: 'Info notification lifetime', value: 5000, - description: 'The time in milliseconds which an information notification ' + - 'will be displayed on-screen for. Setting to Infinity will disable.', + description: `The time in milliseconds which an information notification + will be displayed on-screen for. Setting to Infinity will disable.`, type: 'number', + category: ['notifications'], }, 'metrics:max_buckets': { + name: 'Maximum buckets', value: 2000, - description: 'The maximum number of buckets a single datasource can return' + description: `The maximum number of buckets a single datasource can return` }, 'state:storeInSessionStorage': { + name: 'Store URLs in session storage', value: false, - description: 'The URL can sometimes grow to be too large for some browsers to ' + - 'handle. To counter-act this we are testing if storing parts of the URL in ' + - 'sessions storage could help. Please let us know how it goes!' + description: `The URL can sometimes grow to be too large for some browsers to + handle. To counter-act this we are testing if storing parts of the URL in + session storage could help. Please let us know how it goes!` }, 'indexPattern:placeholder': { + name: 'Index pattern placeholder', value: 'logstash-*', - description: 'The placeholder for the field "Index name or pattern" in the "Settings > Indices" tab.', + description: `The placeholder for the field "Index name or pattern" in the "Settings > Indices" tab.`, }, 'context:defaultSize': { + name: 'Context size', value: 5, - description: 'The number of surrounding entries to show in the context view', + description: `The number of surrounding entries to show in the context view`, + category: ['discover'], }, 'context:step': { + name: 'Context size step', value: 5, - description: 'The step size to increment or decrement the context size by', + description: `The step size to increment or decrement the context size by`, + category: ['discover'], }, 'context:tieBreakerFields': { + name: 'Tie breaker fields', value: ['_doc'], - description: 'A comma-separated list of fields to use for tiebreaking between documents ' + - 'that have the same timestamp value. From this list the first field that ' + - 'is present and sortable in the current index pattern is used.', + description: `A comma-separated list of fields to use for tie-breaking between documents + that have the same timestamp value. From this list the first field that + is present and sortable in the current index pattern is used.`, + category: ['discover'], }, }; } diff --git a/src/core_plugins/markdown_vis/index.js b/src/core_plugins/markdown_vis/index.js index 1ceb7c70649d99..5a1b426ec1deed 100644 --- a/src/core_plugins/markdown_vis/index.js +++ b/src/core_plugins/markdown_vis/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function (kibana) { return new kibana.Plugin({ diff --git a/src/core_plugins/markdown_vis/public/markdown_vis.js b/src/core_plugins/markdown_vis/public/markdown_vis.js index 192003cbe72014..6f7a6e8cddd455 100644 --- a/src/core_plugins/markdown_vis/public/markdown_vis.js +++ b/src/core_plugins/markdown_vis/public/markdown_vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './markdown_vis.less'; import { MarkdownVisWrapper } from './markdown_vis_controller'; import { VisFactoryProvider } from 'ui/vis/vis_factory'; diff --git a/src/core_plugins/markdown_vis/public/markdown_vis_controller.js b/src/core_plugins/markdown_vis/public/markdown_vis_controller.js index 765817d8877a03..455b1879ed93ec 100644 --- a/src/core_plugins/markdown_vis/public/markdown_vis_controller.js +++ b/src/core_plugins/markdown_vis/public/markdown_vis_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component } from 'react'; import { Markdown } from 'ui/markdown/markdown'; diff --git a/src/core_plugins/markdown_vis/public/markdown_vis_controller.test.js b/src/core_plugins/markdown_vis/public/markdown_vis_controller.test.js index 0867d995745906..9857567071de87 100644 --- a/src/core_plugins/markdown_vis/public/markdown_vis_controller.test.js +++ b/src/core_plugins/markdown_vis/public/markdown_vis_controller.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, mount } from 'enzyme'; import { MarkdownVisWrapper } from './markdown_vis_controller'; diff --git a/src/core_plugins/metric_vis/index.js b/src/core_plugins/metric_vis/index.js index cba768a6aaf26b..37bd915ab4308c 100644 --- a/src/core_plugins/metric_vis/index.js +++ b/src/core_plugins/metric_vis/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function (kibana) { return new kibana.Plugin({ diff --git a/src/core_plugins/metric_vis/public/__tests__/metric_vis.js b/src/core_plugins/metric_vis/public/__tests__/metric_vis.js index 92e77aed943927..10b16f0652c5bd 100644 --- a/src/core_plugins/metric_vis/public/__tests__/metric_vis.js +++ b/src/core_plugins/metric_vis/public/__tests__/metric_vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js b/src/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js index 496b79572478f9..313872b4fd0934 100644 --- a/src/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js +++ b/src/core_plugins/metric_vis/public/__tests__/metric_vis_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { MetricVisComponent } from '../metric_vis_controller'; diff --git a/src/core_plugins/metric_vis/public/components/metric_vis_value.js b/src/core_plugins/metric_vis/public/components/metric_vis_value.js index 7eb86e03d8c52f..acf05a4bd5d542 100644 --- a/src/core_plugins/metric_vis/public/components/metric_vis_value.js +++ b/src/core_plugins/metric_vis/public/components/metric_vis_value.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; diff --git a/src/core_plugins/metric_vis/public/metric_vis.js b/src/core_plugins/metric_vis/public/metric_vis.js index 50330095d8db40..4d25bad420da26 100644 --- a/src/core_plugins/metric_vis/public/metric_vis.js +++ b/src/core_plugins/metric_vis/public/metric_vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './metric_vis.less'; import './metric_vis_params'; import { VisFactoryProvider } from 'ui/vis/vis_factory'; diff --git a/src/core_plugins/metric_vis/public/metric_vis_controller.js b/src/core_plugins/metric_vis/public/metric_vis_controller.js index b900cafb69e5b6..3afcace106c74c 100644 --- a/src/core_plugins/metric_vis/public/metric_vis_controller.js +++ b/src/core_plugins/metric_vis/public/metric_vis_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import React, { Component } from 'react'; import { getHeatmapColors } from 'ui/vislib/components/color/heatmap_color'; @@ -65,6 +84,11 @@ export class MetricVisComponent extends Component { return isColorDark(parseInt(color[1]), parseInt(color[2]), parseInt(color[3])); } + _getFormattedValue(fieldFormatter, value) { + if (_.isNaN(value)) return '-'; + return fieldFormatter(value); + } + _processTableGroups(tableGroups) { const config = this.props.vis.params.metric; const isPercentageMode = config.percentageMode; @@ -101,7 +125,7 @@ export class MetricVisComponent extends Component { } if (aggConfig) { - if (!isPercentageMode) value = aggConfig.fieldFormatter('html')(value); + if (!isPercentageMode) value = this._getFormattedValue(aggConfig.fieldFormatter('html'), value); if (bucketAgg) { const bucketValue = bucketAgg.fieldFormatter('text')(row[0]); title = `${bucketValue} - ${aggConfig.makeLabel()}`; diff --git a/src/core_plugins/metric_vis/public/metric_vis_params.js b/src/core_plugins/metric_vis/public/metric_vis_params.js index 5efe6206e03f5c..e0ee85f966fffa 100644 --- a/src/core_plugins/metric_vis/public/metric_vis_params.js +++ b/src/core_plugins/metric_vis/public/metric_vis_params.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from 'ui/modules'; import metricVisParamsTemplate from './metric_vis_params.html'; import _ from 'lodash'; diff --git a/src/core_plugins/metrics/common/__tests__/agg_lookup.js b/src/core_plugins/metrics/common/__tests__/agg_lookup.js index f5bc08f02db283..1c22c6bc7d38b6 100644 --- a/src/core_plugins/metrics/common/__tests__/agg_lookup.js +++ b/src/core_plugins/metrics/common/__tests__/agg_lookup.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { expect } from 'chai'; import { createOptions, isBasicAgg } from '../agg_lookup'; diff --git a/src/core_plugins/metrics/common/__tests__/calculate_label.js b/src/core_plugins/metrics/common/__tests__/calculate_label.js index 8496241dcd99d6..eee4e7df1b3ca6 100644 --- a/src/core_plugins/metrics/common/__tests__/calculate_label.js +++ b/src/core_plugins/metrics/common/__tests__/calculate_label.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { expect } from 'chai'; import calculateLabel from '../calculate_label'; diff --git a/src/core_plugins/metrics/common/__tests__/get_last_value.js b/src/core_plugins/metrics/common/__tests__/get_last_value.js index 681c033842adf4..4b79e7e76e7399 100644 --- a/src/core_plugins/metrics/common/__tests__/get_last_value.js +++ b/src/core_plugins/metrics/common/__tests__/get_last_value.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { expect } from 'chai'; import getLastValue from '../get_last_value'; diff --git a/src/core_plugins/metrics/common/agg_lookup.js b/src/core_plugins/metrics/common/agg_lookup.js index a4d661a9723606..b738442ff6c1fd 100644 --- a/src/core_plugins/metrics/common/agg_lookup.js +++ b/src/core_plugins/metrics/common/agg_lookup.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; const lookup = { count: 'Count', diff --git a/src/core_plugins/metrics/common/basic_aggs.js b/src/core_plugins/metrics/common/basic_aggs.js index 9a5c12306f096b..e6400217956160 100644 --- a/src/core_plugins/metrics/common/basic_aggs.js +++ b/src/core_plugins/metrics/common/basic_aggs.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default [ 'count', 'avg', diff --git a/src/core_plugins/metrics/common/calculate_label.js b/src/core_plugins/metrics/common/calculate_label.js index c0798ee4418633..b6e8dd3dce1b45 100644 --- a/src/core_plugins/metrics/common/calculate_label.js +++ b/src/core_plugins/metrics/common/calculate_label.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { includes, startsWith } from 'lodash'; import lookup from './agg_lookup'; const paths = [ diff --git a/src/core_plugins/metrics/common/get_last_value.js b/src/core_plugins/metrics/common/get_last_value.js index 834cbd0695841c..4af74c623b5dd1 100644 --- a/src/core_plugins/metrics/common/get_last_value.js +++ b/src/core_plugins/metrics/common/get_last_value.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export default (data, lookback = 1) => { if (_.isNumber(data)) return data; diff --git a/src/core_plugins/metrics/common/interval_regexp.js b/src/core_plugins/metrics/common/interval_regexp.js index d7dce5eeabf448..1813a8389c6d75 100644 --- a/src/core_plugins/metrics/common/interval_regexp.js +++ b/src/core_plugins/metrics/common/interval_regexp.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import dateMath from '@kbn/datemath'; export const GTE_INTERVAL_RE = new RegExp(`^>=([\\d\\.]*\\s*(${dateMath.units.join('|')}))$`); export const INTERVAL_STRING_RE = new RegExp('^([0-9\\.]*)\\s*(' + dateMath.units.join('|') + ')$'); diff --git a/src/core_plugins/metrics/index.js b/src/core_plugins/metrics/index.js index 8593f377e959ed..886d57e3dcbd83 100644 --- a/src/core_plugins/metrics/index.js +++ b/src/core_plugins/metrics/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import fieldsRoutes from './server/routes/fields'; import visDataRoutes from './server/routes/vis'; diff --git a/src/core_plugins/metrics/public/components/add_delete_buttons.js b/src/core_plugins/metrics/public/components/add_delete_buttons.js index bbef0da6e56669..004445d9c45adf 100644 --- a/src/core_plugins/metrics/public/components/add_delete_buttons.js +++ b/src/core_plugins/metrics/public/components/add_delete_buttons.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import { EuiToolTip } from '@elastic/eui'; diff --git a/src/core_plugins/metrics/public/components/add_delete_buttons.test.js b/src/core_plugins/metrics/public/components/add_delete_buttons.test.js index 202dc891c67d62..d414149b6634c3 100644 --- a/src/core_plugins/metrics/public/components/add_delete_buttons.test.js +++ b/src/core_plugins/metrics/public/components/add_delete_buttons.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { expect } from 'chai'; import { shallow } from 'enzyme'; diff --git a/src/core_plugins/metrics/public/components/aggs/agg.js b/src/core_plugins/metrics/public/components/aggs/agg.js index 69d7177584f258..734ec440433e0c 100644 --- a/src/core_plugins/metrics/public/components/aggs/agg.js +++ b/src/core_plugins/metrics/public/components/aggs/agg.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import aggToComponent from '../lib/agg_to_component'; diff --git a/src/core_plugins/metrics/public/components/aggs/agg_row.js b/src/core_plugins/metrics/public/components/aggs/agg_row.js index 15b271ea637e0a..1e5fea49c9a60f 100644 --- a/src/core_plugins/metrics/public/components/aggs/agg_row.js +++ b/src/core_plugins/metrics/public/components/aggs/agg_row.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import _ from 'lodash'; diff --git a/src/core_plugins/metrics/public/components/aggs/agg_select.js b/src/core_plugins/metrics/public/components/aggs/agg_select.js index 786bbe6698803a..91e3c9478b154b 100644 --- a/src/core_plugins/metrics/public/components/aggs/agg_select.js +++ b/src/core_plugins/metrics/public/components/aggs/agg_select.js @@ -1,6 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Select from 'react-select'; +import React from 'react'; +import { + EuiComboBox, +} from '@elastic/eui'; const metricAggs = [ { label: 'Average', value: 'avg' }, @@ -44,89 +65,12 @@ const specialAggs = [ { label: 'Math', value: 'math' }, ]; -class AggSelectOption extends Component { - constructor(props) { - super(props); - this.handleMouseMove = this.handleMouseMove.bind(this); - this.handleMouseEnter = this.handleMouseEnter.bind(this); - this.handleMouseDown = this.handleMouseDown.bind(this); - } - - handleMouseDown(event) { - event.preventDefault(); - event.stopPropagation(); - this.props.onSelect(this.props.option, event); - } - - handleMouseEnter(event) { - this.props.onFocus(this.props.option, event); - } - - handleMouseMove(event) { - if (this.props.isFocused) return; - this.props.onFocus(this.props.option, event); - } - - render() { - const { label, heading, pipeline } = this.props.option; - const style = { - paddingLeft: heading ? 0 : 10, - }; - // We can ignore that the
does not have keyboard handlers even though - // it has mouse handlers, since react-select still takes care, that this works - // well with keyboard. - /* eslint-disable jsx-a11y/no-static-element-interactions */ - if (heading) { - let note; - if (pipeline) { - note = ( - - (requires child aggregation) - - ); - } - return ( -
- - {label} - {note} - -
- ); - } - return ( -
- - {this.props.children} - -
- ); - /* eslint-enable jsx-a11y/no-static-element-interactions */ - } -} - -AggSelectOption.props = { - children: PropTypes.node, - className: PropTypes.string, - isDisabled: PropTypes.bool, - isFocused: PropTypes.bool, - isSelected: PropTypes.bool, - onFocus: PropTypes.func, - onSelect: PropTypes.func, - option: PropTypes.object.isRequired, -}; +const allAggOptions = [ + ...metricAggs, + ...pipelineAggs, + ...siblingAggs, + ...specialAggs +]; function filterByPanelType(panelType) { return agg => { @@ -136,7 +80,12 @@ function filterByPanelType(panelType) { } function AggSelect(props) { - const { siblings, panelType } = props; + const { siblings, panelType, value } = props; + + const selectedOption = allAggOptions.find(option => { + return value === option.value; + }); + const selectedOptions = selectedOption ? [selectedOption] : []; let enablePipelines = siblings.some( s => !!metricAggs.find(m => m.value === s.type) @@ -150,55 +99,39 @@ function AggSelect(props) { options = [ { label: 'Metric Aggregations', - value: null, - heading: true, - disabled: true, + options: metricAggs, }, - ...metricAggs, { label: 'Parent Pipeline Aggregations', - value: null, - pipeline: true, - heading: true, - disabled: true, + options: pipelineAggs + .filter(filterByPanelType(panelType)) + .map(agg => ({ ...agg, disabled: !enablePipelines })) }, - ...pipelineAggs - .filter(filterByPanelType(panelType)) - .map(agg => ({ ...agg, disabled: !enablePipelines })), { label: 'Sibling Pipeline Aggregations', - value: null, - pipeline: true, - heading: true, - disabled: true, + options: siblingAggs.map(agg => ({ ...agg, disabled: !enablePipelines })), }, - ...siblingAggs.map(agg => ({ ...agg, disabled: !enablePipelines })), { label: 'Special Aggregations', - value: null, - pipeline: true, - heading: true, - disabled: true, + options: specialAggs.map(agg => ({ ...agg, disabled: !enablePipelines })), }, - ...specialAggs.map(agg => ({ ...agg, disabled: !enablePipelines })), ]; } - const handleChange = value => { - if (!value) return; - if (value.disabled) return; - if (value.value) props.onChange(value); + const handleChange = selectedOptions => { + if (!selectedOptions || selectedOptions.length <= 0) return; + props.onChange(selectedOptions); }; return (
- ); } diff --git a/src/core_plugins/metrics/public/components/aggs/filter_ratio.js b/src/core_plugins/metrics/public/components/aggs/filter_ratio.js index c8d4fb0c53e701..6db2d61af91347 100644 --- a/src/core_plugins/metrics/public/components/aggs/filter_ratio.js +++ b/src/core_plugins/metrics/public/components/aggs/filter_ratio.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import AggSelect from './agg_select'; diff --git a/src/core_plugins/metrics/public/components/aggs/math.js b/src/core_plugins/metrics/public/components/aggs/math.js index 28563c81653bd0..34d25ea7bf82ac 100644 --- a/src/core_plugins/metrics/public/components/aggs/math.js +++ b/src/core_plugins/metrics/public/components/aggs/math.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component } from 'react'; import PropTypes from 'prop-types'; import _ from 'lodash'; diff --git a/src/core_plugins/metrics/public/components/aggs/metric_select.js b/src/core_plugins/metrics/public/components/aggs/metric_select.js index 4ba469b7c0b029..fb12f085a62542 100644 --- a/src/core_plugins/metrics/public/components/aggs/metric_select.js +++ b/src/core_plugins/metrics/public/components/aggs/metric_select.js @@ -1,7 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import _ from 'lodash'; -import Select from 'react-select'; +import { + EuiComboBox, +} from '@elastic/eui'; import calculateSiblings from '../lib/calculate_siblings'; import calculateLabel from '../../../common/calculate_label'; import basicAggs from '../../../common/basic_aggs'; @@ -67,14 +88,20 @@ function MetricSelect(props) { const label = calculateLabel(row, metrics); return { value: row.id, label }; }); + const allOptions = [...options, ...props.additionalOptions, ...percentileOptions]; + + const selectedOption = allOptions.find(option => { + return value === option.value; + }); + const selectedOptions = selectedOption ? [selectedOption] : []; return ( -
@@ -90,12 +119,13 @@ export const MovingAverageAgg = props => {
-
-
diff --git a/src/core_plugins/metrics/public/components/aggs/std_sibling.js b/src/core_plugins/metrics/public/components/aggs/std_sibling.js index e536371983afd3..4e4fe2e9e9406d 100644 --- a/src/core_plugins/metrics/public/components/aggs/std_sibling.js +++ b/src/core_plugins/metrics/public/components/aggs/std_sibling.js @@ -1,13 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import AggRow from './agg_row'; import MetricSelect from './metric_select'; import AggSelect from './agg_select'; -import Select from 'react-select'; import createChangeHandler from '../lib/create_change_handler'; import createSelectHandler from '../lib/create_select_handler'; import createTextHandler from '../lib/create_text_handler'; -import { htmlIdGenerator } from '@elastic/eui'; +import { + htmlIdGenerator, + EuiComboBox, +} from '@elastic/eui'; export const StandardSiblingAgg = props => { const { siblings } = props; @@ -39,15 +60,19 @@ export const StandardSiblingAgg = props => { { label: 'Lower Bound', value: 'lower' }, { label: 'Bounds Band', value: 'band' } ]; + const selectedModeOption = modeOptions.find(option => { + return model.mode === option.value; + }); stdDev.mode = (
-
@@ -113,13 +141,14 @@ export const TopHitAgg = props => { -
{ + return (selectedOptions) => { + if (selectedOptions.length < 1) { + return; + } + + let newValue; if (name === 'decimals') { - value = this.decimals; + newValue = this.decimals.value; + } else { + newValue = selectedOptions[0].value; } + this.setState({ - [name]: value.value + [name]: newValue }, () => { const { from, to, decimals } = this.state; - this.props.onChange({ + this.props.onChange([{ value: `${from},${to},${decimals}` - }); + }]); }); }; } @@ -73,39 +106,51 @@ class DataFormatPicker extends Component { { label: 'Duration', value: 'duration' }, { label: 'Custom', value: 'custom' } ]; + const selectedOption = options.find(option => { + return defaultValue === option.value; + }); let custom; if (defaultValue === 'duration') { const [from, to, decimals] = value.split(','); + const selectedFrom = durationInputOptions.find(option => { + return from === option.value; + }); + const selectedTo = durationOutputOptions.find(option => { + return to === option.value; + }); return (
{this.props.label}
-
To
-
{custom} diff --git a/src/core_plugins/metrics/public/components/error.js b/src/core_plugins/metrics/public/components/error.js index 675542d37baf0e..7aaa7d0da2c6b6 100644 --- a/src/core_plugins/metrics/public/components/error.js +++ b/src/core_plugins/metrics/public/components/error.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import _ from 'lodash'; diff --git a/src/core_plugins/metrics/public/components/icon_select.js b/src/core_plugins/metrics/public/components/icon_select.js index 70dd746c1a7692..d56657dba6824d 100644 --- a/src/core_plugins/metrics/public/components/icon_select.js +++ b/src/core_plugins/metrics/public/components/icon_select.js @@ -1,77 +1,31 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Select from 'react-select'; - -class IconOption extends Component { - - constructor(props) { - super(props); - this.handleMouseMove = this.handleMouseMove.bind(this); - this.handleMouseEnter = this.handleMouseEnter.bind(this); - this.handleMouseDown = this.handleMouseDown.bind(this); - } - - handleMouseDown(event) { - event.preventDefault(); - event.stopPropagation(); - this.props.onSelect(this.props.option, event); - } - - handleMouseEnter(event) { - this.props.onFocus(this.props.option, event); - } - - handleMouseMove(event) { - if (this.props.isFocused) return; - this.props.onFocus(this.props.option, event); - } - - render() { - const icon = this.props.option.value; - const label = this.props.option.label; - // We can ignore that the
does not have keyboard handlers even though - // it has mouse handlers, since react-select still takes care, that this works - // well with keyboard. - /* eslint-disable jsx-a11y/no-static-element-interactions */ - return ( -
- - -
- ); - /* eslint-enable jsx-a11y/no-static-element-interactions */ - } - -} - -IconOption.propTypes = { - children: PropTypes.node, - className: PropTypes.string, - isDisabled: PropTypes.bool, - isFocused: PropTypes.bool, - isSelected: PropTypes.bool, - onFocus: PropTypes.func, - onSelect: PropTypes.func, - option: PropTypes.object.isRequired, -}; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import PropTypes from 'prop-types'; +import React from 'react'; +import { + EuiComboBox, +} from '@elastic/eui'; -function IconValue(props) { - const icon = props.value && props.value.value; - const label = props.value && props.value.label; +function renderOption(option) { + const icon = option.value; + const label = option.label; return (
- { props.children } + { label }
); } -IconValue.propTypes = { - children: PropTypes.node, - placeholder: PropTypes.string, - value: PropTypes.object.isRequired -}; - function IconSelect(props) { + const selectedIcon = props.icons.find(option => { + return props.value === option.value; + }); return ( -
diff --git a/src/core_plugins/metrics/public/components/panel_config/markdown.js b/src/core_plugins/metrics/public/components/panel_config/markdown.js index 966162b40f4521..29d419b5966963 100644 --- a/src/core_plugins/metrics/public/components/panel_config/markdown.js +++ b/src/core_plugins/metrics/public/components/panel_config/markdown.js @@ -1,9 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; import SeriesEditor from '../series_editor'; import { IndexPattern } from '../index_pattern'; import 'brace/mode/less'; -import Select from 'react-select'; import createSelectHandler from '../lib/create_select_handler'; import createTextHandler from '../lib/create_text_handler'; import ColorPicker from '../color_picker'; @@ -11,7 +29,10 @@ import YesNo from '../yes_no'; import MarkdownEditor from '../markdown_editor'; import less from 'less/lib/less-browser'; import { KuiCodeEditor } from '@kbn/ui-framework/components'; -import { htmlIdGenerator } from '@elastic/eui'; +import { + htmlIdGenerator, + EuiComboBox, +} from '@elastic/eui'; const lessC = less(window, { env: 'production' }); class MarkdownPanelConfig extends Component { @@ -54,6 +75,9 @@ class MarkdownPanelConfig extends Component { { label: 'Middle', value: 'middle' }, { label: 'Bottom', value: 'bottom' } ]; + const selectedAlignOption = alignOptions.find(option => { + return model.markdown_vertical_align === option.value; + }); let view; if (selectedTab === 'markdown') { view = (); @@ -110,13 +134,13 @@ class MarkdownPanelConfig extends Component { Vertical Alignment
- +
+ +
+
@@ -114,12 +160,13 @@ class TimeseriesPanelConfig extends Component { />
- ); diff --git a/src/core_plugins/metrics/public/components/splits/terms.js b/src/core_plugins/metrics/public/components/splits/terms.js index ddedc20210c296..2905ad83d2bc65 100644 --- a/src/core_plugins/metrics/public/components/splits/terms.js +++ b/src/core_plugins/metrics/public/components/splits/terms.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import GroupBySelect from './group_by_select'; @@ -5,7 +24,9 @@ import createTextHandler from '../lib/create_text_handler'; import createSelectHandler from '../lib/create_select_handler'; import FieldSelect from '../aggs/field_select'; import MetricSelect from '../aggs/metric_select'; -import Select from 'react-select'; +import { + EuiComboBox, +} from '@elastic/eui'; export const SplitByTerms = props => { const handleTextChange = createTextHandler(props.onChange); @@ -21,6 +42,9 @@ export const SplitByTerms = props => { { value: 'desc', label: 'Descending' }, { value: 'asc', label: 'Ascending' }, ]; + const selectedDirectionOption = dirOptions.find(option => { + return model.terms_direction === option.value; + }); return (
@@ -61,11 +85,12 @@ export const SplitByTerms = props => {
Direction
-
diff --git a/src/core_plugins/metrics/public/components/vis_types/table/is_sortable.js b/src/core_plugins/metrics/public/components/vis_types/table/is_sortable.js index 5364efd90c58da..3f7e20a8df3581 100644 --- a/src/core_plugins/metrics/public/components/vis_types/table/is_sortable.js +++ b/src/core_plugins/metrics/public/components/vis_types/table/is_sortable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import basicAggs from '../../../../common/basic_aggs'; export function isSortable(metric) { return basicAggs.includes(metric.type); diff --git a/src/core_plugins/metrics/public/components/vis_types/table/series.js b/src/core_plugins/metrics/public/components/vis_types/table/series.js index e9ad38a7011f00..f44df0306f9f55 100644 --- a/src/core_plugins/metrics/public/components/vis_types/table/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/table/series.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import PropTypes from 'prop-types'; import AddDeleteButtons from '../../add_delete_buttons'; diff --git a/src/core_plugins/metrics/public/components/vis_types/table/vis.js b/src/core_plugins/metrics/public/components/vis_types/table/vis.js index 5d10ca14936620..eaeb12dfa116d4 100644 --- a/src/core_plugins/metrics/public/components/vis_types/table/vis.js +++ b/src/core_plugins/metrics/public/components/vis_types/table/vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import React, { Component } from 'react'; import PropTypes from 'prop-types'; diff --git a/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js b/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js index b554716c19939d..811d4204293b96 100644 --- a/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js +++ b/src/core_plugins/metrics/public/components/vis_types/timeseries/config.js @@ -1,12 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; -import Select from 'react-select'; import DataFormatPicker from '../../data_format_picker'; import createSelectHandler from '../../lib/create_select_handler'; import YesNo from '../../yes_no'; import createTextHandler from '../../lib/create_text_handler'; import { IndexPattern } from '../../index_pattern'; -import { htmlIdGenerator } from '@elastic/eui'; +import { + htmlIdGenerator, + EuiComboBox, +} from '@elastic/eui'; function TimeseriesConfig(props) { const handleSelectChange = createSelectHandler(props.onChange); @@ -32,21 +53,33 @@ function TimeseriesConfig(props) { { label: 'Stacked', value: 'stacked' }, { label: 'Percent', value: 'percent' } ]; + const selectedStackedOption = stackedOptions.find(option => { + return model.stacked === option.value; + }); const positionOptions = [ { label: 'Right', value: 'right' }, { label: 'Left', value: 'left' } ]; + const selectedAxisPosOption = positionOptions.find(option => { + return model.axis_position === option.value; + }); const chartTypeOptions = [ { label: 'Bar', value: 'bar' }, { label: 'Line', value: 'line' } ]; + const selectedChartTypeOption = chartTypeOptions.find(option => { + return model.chart_type === option.value; + }); const splitColorOptions = [ { label: 'Gradient', value: 'gradient' }, { label: 'Rainbow', value: 'rainbow' } ]; + const selectedSplitColorOption = splitColorOptions.find(option => { + return model.split_color_mode === option.value; + }); let type; if (model.chart_type === 'line') { @@ -56,24 +89,26 @@ function TimeseriesConfig(props) { Chart Type
-
-
-
diff --git a/src/core_plugins/metrics/public/components/vis_types/timeseries/series.js b/src/core_plugins/metrics/public/components/vis_types/timeseries/series.js index b3e28fd9e3e577..b82f8dace2b70c 100644 --- a/src/core_plugins/metrics/public/components/vis_types/timeseries/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/timeseries/series.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import ColorPicker from '../../color_picker'; diff --git a/src/core_plugins/metrics/public/components/vis_types/timeseries/vis.js b/src/core_plugins/metrics/public/components/vis_types/timeseries/vis.js index e0df410f576606..73ce37578ff310 100644 --- a/src/core_plugins/metrics/public/components/vis_types/timeseries/vis.js +++ b/src/core_plugins/metrics/public/components/vis_types/timeseries/vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; import tickFormatter from '../../lib/tick_formatter'; @@ -71,6 +90,11 @@ class TimeseriesVisualization extends Component { if (model.axis_min) mainAxis.min = model.axis_min; if (model.axis_max) mainAxis.max = model.axis_max; + if (model.axis_scale === 'log') { + mainAxis.mode = 'log'; + mainAxis.transform = value => value > 0 ? Math.log(value) / Math.LN10 : null; + mainAxis.inverseTransform = value => Math.pow(10, value); + } const yaxes = [mainAxis]; diff --git a/src/core_plugins/metrics/public/components/vis_types/top_n/series.js b/src/core_plugins/metrics/public/components/vis_types/top_n/series.js index ade1aa206f3140..5daa0d442eb534 100644 --- a/src/core_plugins/metrics/public/components/vis_types/top_n/series.js +++ b/src/core_plugins/metrics/public/components/vis_types/top_n/series.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import ColorPicker from '../../color_picker'; diff --git a/src/core_plugins/metrics/public/components/vis_types/top_n/vis.js b/src/core_plugins/metrics/public/components/vis_types/top_n/vis.js index 7aa583f27c0197..e2c0ba68729945 100644 --- a/src/core_plugins/metrics/public/components/vis_types/top_n/vis.js +++ b/src/core_plugins/metrics/public/components/vis_types/top_n/vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import tickFormatter from '../../lib/tick_formatter'; import TopN from '../../../visualizations/components/top_n'; import getLastValue from '../../../../common/get_last_value'; diff --git a/src/core_plugins/metrics/public/components/vis_with_splits.js b/src/core_plugins/metrics/public/components/vis_with_splits.js index c87ab55831a1c0..18b0bca7c8869c 100644 --- a/src/core_plugins/metrics/public/components/vis_with_splits.js +++ b/src/core_plugins/metrics/public/components/vis_with_splits.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { getDisplayName } from './lib/get_display_name'; import { last, findIndex, first } from 'lodash'; diff --git a/src/core_plugins/metrics/public/components/visualization.js b/src/core_plugins/metrics/public/components/visualization.js index ca145c89d16395..2279244ab10714 100644 --- a/src/core_plugins/metrics/public/components/visualization.js +++ b/src/core_plugins/metrics/public/components/visualization.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import _ from 'lodash'; diff --git a/src/core_plugins/metrics/public/components/yes_no.js b/src/core_plugins/metrics/public/components/yes_no.js index 41b7df6870063d..f76d7b96b42235 100644 --- a/src/core_plugins/metrics/public/components/yes_no.js +++ b/src/core_plugins/metrics/public/components/yes_no.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import _ from 'lodash'; diff --git a/src/core_plugins/metrics/public/components/yes_no.test.js b/src/core_plugins/metrics/public/components/yes_no.test.js index a2b05d725493c4..38ab90b61de076 100644 --- a/src/core_plugins/metrics/public/components/yes_no.test.js +++ b/src/core_plugins/metrics/public/components/yes_no.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { expect } from 'chai'; import { shallow } from 'enzyme'; diff --git a/src/core_plugins/metrics/public/kbn_vis_types/editor_controller.js b/src/core_plugins/metrics/public/kbn_vis_types/editor_controller.js index f2b0f32e77c58b..2be8f8903a3279 100644 --- a/src/core_plugins/metrics/public/kbn_vis_types/editor_controller.js +++ b/src/core_plugins/metrics/public/kbn_vis_types/editor_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { SavedObjectsClientProvider } from 'ui/saved_objects'; diff --git a/src/core_plugins/metrics/public/kbn_vis_types/index.js b/src/core_plugins/metrics/public/kbn_vis_types/index.js index c530cfca52a413..b5b947a4007c51 100644 --- a/src/core_plugins/metrics/public/kbn_vis_types/index.js +++ b/src/core_plugins/metrics/public/kbn_vis_types/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import '../visualizations/less/main.less'; import '../less/main.less'; import image from '../images/icon-visualbuilder.svg'; @@ -52,6 +71,7 @@ export default function MetricsVisProvider(Private) { interval: 'auto', axis_position: 'left', axis_formatter: 'number', + axis_scale: 'normal', show_legend: 1, show_grid: 1 }, diff --git a/src/core_plugins/metrics/public/kbn_vis_types/request_handler.js b/src/core_plugins/metrics/public/kbn_vis_types/request_handler.js index edfc0ff662cc4d..a64c2f6458ad7a 100644 --- a/src/core_plugins/metrics/public/kbn_vis_types/request_handler.js +++ b/src/core_plugins/metrics/public/kbn_vis_types/request_handler.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { validateInterval } from '../lib/validate_interval'; import { dashboardContextProvider } from 'plugins/kibana/dashboard/dashboard_context'; import { timezoneProvider } from 'ui/vis/lib/timezone'; diff --git a/src/core_plugins/metrics/public/lib/__tests__/create_brush_handler.js b/src/core_plugins/metrics/public/lib/__tests__/create_brush_handler.js index 9c1b865215ccbd..169572b53e1fe2 100644 --- a/src/core_plugins/metrics/public/lib/__tests__/create_brush_handler.js +++ b/src/core_plugins/metrics/public/lib/__tests__/create_brush_handler.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import createBrushHandler from '../create_brush_handler'; import moment from 'moment'; import { expect } from 'chai'; diff --git a/src/core_plugins/metrics/public/lib/__tests__/extract_index_pattern.js b/src/core_plugins/metrics/public/lib/__tests__/extract_index_pattern.js index ea181c396df400..8d085140b17614 100644 --- a/src/core_plugins/metrics/public/lib/__tests__/extract_index_pattern.js +++ b/src/core_plugins/metrics/public/lib/__tests__/extract_index_pattern.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { extractIndexPatterns } from '../extract_index_patterns'; import { expect } from 'chai'; describe('extractIndexPatterns(vis)', () => { diff --git a/src/core_plugins/metrics/public/lib/create_brush_handler.js b/src/core_plugins/metrics/public/lib/create_brush_handler.js index b4eb7ca25e1c57..f4e6f3c5592df4 100644 --- a/src/core_plugins/metrics/public/lib/create_brush_handler.js +++ b/src/core_plugins/metrics/public/lib/create_brush_handler.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import moment from 'moment'; export default (timefilter) => ranges => { //$scope.$evalAsync(() => { diff --git a/src/core_plugins/metrics/public/lib/create_new_panel.js b/src/core_plugins/metrics/public/lib/create_new_panel.js index dda21a31cdfeb2..5f6927fe4b240d 100644 --- a/src/core_plugins/metrics/public/lib/create_new_panel.js +++ b/src/core_plugins/metrics/public/lib/create_new_panel.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import newSeriesFn from '../components/lib/new_series_fn'; import uuid from 'uuid'; export default () => { diff --git a/src/core_plugins/metrics/public/lib/extract_index_patterns.js b/src/core_plugins/metrics/public/lib/extract_index_patterns.js index 81bb6a0cd71050..c7e4f555955e05 100644 --- a/src/core_plugins/metrics/public/lib/extract_index_patterns.js +++ b/src/core_plugins/metrics/public/lib/extract_index_patterns.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uniq } from 'lodash'; export function extractIndexPatterns(vis) { const patternsToFetch = []; diff --git a/src/core_plugins/metrics/public/lib/fetch_fields.js b/src/core_plugins/metrics/public/lib/fetch_fields.js index e14cdfef9a7868..5fc68f14378eb4 100644 --- a/src/core_plugins/metrics/public/lib/fetch_fields.js +++ b/src/core_plugins/metrics/public/lib/fetch_fields.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const FetchFieldsProvider = (Notifier, $http) => { const notify = new Notifier({ location: 'Metrics' }); return (indexPatterns = ['*']) => { diff --git a/src/core_plugins/metrics/public/lib/validate_interval.js b/src/core_plugins/metrics/public/lib/validate_interval.js index 4ad3fa4a4dd332..00a8c0bef2aba4 100644 --- a/src/core_plugins/metrics/public/lib/validate_interval.js +++ b/src/core_plugins/metrics/public/lib/validate_interval.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { parseInterval } from 'ui/utils/parse_interval'; import { GTE_INTERVAL_RE } from '../../common/interval_regexp'; export function validateInterval(bounds, panel, maxBuckets) { diff --git a/src/core_plugins/metrics/public/services/__tests__/executor_provider.js b/src/core_plugins/metrics/public/services/__tests__/executor_provider.js index 36875a3f7fc0cb..f19ac4677ad741 100644 --- a/src/core_plugins/metrics/public/services/__tests__/executor_provider.js +++ b/src/core_plugins/metrics/public/services/__tests__/executor_provider.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { expect } from 'chai'; import sinon from 'sinon'; import executorProvider from '../executor_provider'; @@ -17,8 +36,8 @@ describe('$executor service', () => { $timeout.cancel = (id) => clearTimeout(id); timefilter = new EventEmitter(); - onSpy = sinon.spy((...args) => timefilter.addListener(...args)); - offSpy = sinon.spy((...args) => timefilter.removeListener(...args)); + onSpy = sinon.stub().callsFake((...args) => timefilter.addListener(...args)); + offSpy = sinon.stub().callsFake((...args) => timefilter.removeListener(...args)); timefilter.on = onSpy; timefilter.off = offSpy; @@ -59,13 +78,17 @@ describe('$executor service', () => { it('should execute function if ingorePause is passed (interval set to 1000ms)', (done) => { timefilter.refreshInterval.value = 1000; - executor.register({ execute: () => done() }); + executor.register({ + execute: () => Promise.resolve().then(done) + }); executor.start({ ignorePaused: true }); }); it('should execute function if timefilter is not paused and interval set to 1000ms', (done) => { timefilter.refreshInterval.value = 1000; - executor.register({ execute: () => done() }); + executor.register({ + execute: () => Promise.resolve().then(done) + }); executor.start(); }); diff --git a/src/core_plugins/metrics/public/services/executor.js b/src/core_plugins/metrics/public/services/executor.js index d42004c83efc03..def1db6e3d5e35 100644 --- a/src/core_plugins/metrics/public/services/executor.js +++ b/src/core_plugins/metrics/public/services/executor.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from 'ui/modules'; import executorProvider from './executor_provider'; const uiModule = uiModules.get('kibana/metrics_vis/executor', []); diff --git a/src/core_plugins/metrics/public/services/executor_provider.js b/src/core_plugins/metrics/public/services/executor_provider.js index 8f58c038b0127e..18c23ff67c3ffe 100644 --- a/src/core_plugins/metrics/public/services/executor_provider.js +++ b/src/core_plugins/metrics/public/services/executor_provider.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export default function executorProvider(Promise, $timeout, timefilter) { diff --git a/src/core_plugins/metrics/public/visualizations/components/annotation.js b/src/core_plugins/metrics/public/visualizations/components/annotation.js index 9dc7a6ad1087f9..09ccf8197dc586 100644 --- a/src/core_plugins/metrics/public/visualizations/components/annotation.js +++ b/src/core_plugins/metrics/public/visualizations/components/annotation.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; import moment from 'moment'; diff --git a/src/core_plugins/metrics/public/visualizations/components/flot_chart.js b/src/core_plugins/metrics/public/visualizations/components/flot_chart.js index a85f140c283658..6b303c2e282ff8 100644 --- a/src/core_plugins/metrics/public/visualizations/components/flot_chart.js +++ b/src/core_plugins/metrics/public/visualizations/components/flot_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { findDOMNode } from 'react-dom'; @@ -32,6 +51,7 @@ class FlotChart extends Component { axis.max !== this.props.yaxes[i].max || axis.min !== this.props.yaxes[i].min || axis.axisFormatter !== this.props.yaxes[i].axisFormatter || + axis.mode !== this.props.yaxes[i].mode || axis.axisFormatterTemplate !== this.props.yaxes[i].axisFormatterTemplate ); } diff --git a/src/core_plugins/metrics/public/visualizations/components/gauge.js b/src/core_plugins/metrics/public/visualizations/components/gauge.js index 156acde03d0d16..5d6729b724eb40 100644 --- a/src/core_plugins/metrics/public/visualizations/components/gauge.js +++ b/src/core_plugins/metrics/public/visualizations/components/gauge.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; diff --git a/src/core_plugins/metrics/public/visualizations/components/gauge_vis.js b/src/core_plugins/metrics/public/visualizations/components/gauge_vis.js index 1f381a937b475b..53d0235b15f6d2 100644 --- a/src/core_plugins/metrics/public/visualizations/components/gauge_vis.js +++ b/src/core_plugins/metrics/public/visualizations/components/gauge_vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; import _ from 'lodash'; diff --git a/src/core_plugins/metrics/public/visualizations/components/horizontal_legend.js b/src/core_plugins/metrics/public/visualizations/components/horizontal_legend.js index 0b21f092fc6796..2a76c928d00736 100644 --- a/src/core_plugins/metrics/public/visualizations/components/horizontal_legend.js +++ b/src/core_plugins/metrics/public/visualizations/components/horizontal_legend.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import createLegendSeries from '../lib/create_legend_series'; diff --git a/src/core_plugins/metrics/public/visualizations/components/legend.js b/src/core_plugins/metrics/public/visualizations/components/legend.js index bc1cc5edb6ae65..f5023b58623d53 100644 --- a/src/core_plugins/metrics/public/visualizations/components/legend.js +++ b/src/core_plugins/metrics/public/visualizations/components/legend.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import VerticalLegend from './vertical_legend'; diff --git a/src/core_plugins/metrics/public/visualizations/components/metric.js b/src/core_plugins/metrics/public/visualizations/components/metric.js index eead38f5303b77..29655d76057893 100644 --- a/src/core_plugins/metrics/public/visualizations/components/metric.js +++ b/src/core_plugins/metrics/public/visualizations/components/metric.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; import _ from 'lodash'; @@ -135,7 +154,13 @@ class Metric extends Component {
this.inner = el} className="rhythm_metric__inner" style={styles.inner}>
{ primaryLabel } -
{ primaryValue }
+
+ { primaryValue } +
{ secondarySnippet } {additionalLabel} diff --git a/src/core_plugins/metrics/public/visualizations/components/resize.js b/src/core_plugins/metrics/public/visualizations/components/resize.js index f7b64aa70ee944..2dd47a35ff942e 100644 --- a/src/core_plugins/metrics/public/visualizations/components/resize.js +++ b/src/core_plugins/metrics/public/visualizations/components/resize.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { findDOMNode } from 'react-dom'; diff --git a/src/core_plugins/metrics/public/visualizations/components/timeseries.js b/src/core_plugins/metrics/public/visualizations/components/timeseries.js index ed55a8d272222c..808b33f1c4ec36 100644 --- a/src/core_plugins/metrics/public/visualizations/components/timeseries.js +++ b/src/core_plugins/metrics/public/visualizations/components/timeseries.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; import _ from 'lodash'; diff --git a/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js b/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js index 52ee5688c63ec4..a9a08b25b93476 100644 --- a/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js +++ b/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; import moment from 'moment'; diff --git a/src/core_plugins/metrics/public/visualizations/components/top_n.js b/src/core_plugins/metrics/public/visualizations/components/top_n.js index a1c3ebd6bfedce..88dd043a07f97b 100644 --- a/src/core_plugins/metrics/public/visualizations/components/top_n.js +++ b/src/core_plugins/metrics/public/visualizations/components/top_n.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React, { Component } from 'react'; import getLastValue from '../../../common/get_last_value'; @@ -47,7 +66,7 @@ class TopN extends Component { style={styles.innerBar} /> - { value } + { value } ); }; diff --git a/src/core_plugins/metrics/public/visualizations/components/vertical_legend.js b/src/core_plugins/metrics/public/visualizations/components/vertical_legend.js index 488ea9c9185a55..6b527c132f397a 100644 --- a/src/core_plugins/metrics/public/visualizations/components/vertical_legend.js +++ b/src/core_plugins/metrics/public/visualizations/components/vertical_legend.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import PropTypes from 'prop-types'; import React from 'react'; import createLegendSeries from '../lib/create_legend_series'; diff --git a/src/core_plugins/metrics/public/visualizations/lib/__tests__/calcualte_bar_width.js b/src/core_plugins/metrics/public/visualizations/lib/__tests__/calcualte_bar_width.js index 91762bba2b9fe2..a78ebd901d0124 100644 --- a/src/core_plugins/metrics/public/visualizations/lib/__tests__/calcualte_bar_width.js +++ b/src/core_plugins/metrics/public/visualizations/lib/__tests__/calcualte_bar_width.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { expect } from 'chai'; import calculateBarWidth from '../calculate_bar_width'; diff --git a/src/core_plugins/metrics/public/visualizations/lib/__tests__/get_value_by.js b/src/core_plugins/metrics/public/visualizations/lib/__tests__/get_value_by.js index ac43a53ea3a98d..366e1b13d92e41 100644 --- a/src/core_plugins/metrics/public/visualizations/lib/__tests__/get_value_by.js +++ b/src/core_plugins/metrics/public/visualizations/lib/__tests__/get_value_by.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import getValueBy from '../get_value_by'; import { expect } from 'chai'; diff --git a/src/core_plugins/metrics/public/visualizations/lib/calc_dimensions.js b/src/core_plugins/metrics/public/visualizations/lib/calc_dimensions.js index f038c882c8f0a6..e49724642c8c91 100644 --- a/src/core_plugins/metrics/public/visualizations/lib/calc_dimensions.js +++ b/src/core_plugins/metrics/public/visualizations/lib/calc_dimensions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function calcDimensions(el, scale) { const newWidth = Math.floor(el.clientWidth * scale); const newHeight = Math.floor(el.clientHeight * scale); diff --git a/src/core_plugins/metrics/public/visualizations/lib/calculate_bar_width.js b/src/core_plugins/metrics/public/visualizations/lib/calculate_bar_width.js index 0290049d6e342c..16a95a3ec91e33 100644 --- a/src/core_plugins/metrics/public/visualizations/lib/calculate_bar_width.js +++ b/src/core_plugins/metrics/public/visualizations/lib/calculate_bar_width.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; // bar sizes are measured in milliseconds so this assumes that the different // between timestamps is in milliseconds. A normal bar size is 70% which gives diff --git a/src/core_plugins/metrics/public/visualizations/lib/calculate_corrdinates.js b/src/core_plugins/metrics/public/visualizations/lib/calculate_corrdinates.js index cfe0d8c3fcc31f..65c3ee6bfe642e 100644 --- a/src/core_plugins/metrics/public/visualizations/lib/calculate_corrdinates.js +++ b/src/core_plugins/metrics/public/visualizations/lib/calculate_corrdinates.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { findDOMNode } from 'react-dom'; import calcDimensions from './calc_dimensions'; export default function calculateCorrdinates(innerRef, resizeRef, state) { diff --git a/src/core_plugins/metrics/public/visualizations/lib/colors.js b/src/core_plugins/metrics/public/visualizations/lib/colors.js index 028af4b7e85a56..f61c0a3c9ca957 100644 --- a/src/core_plugins/metrics/public/visualizations/lib/colors.js +++ b/src/core_plugins/metrics/public/visualizations/lib/colors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default { lineColor: 'rgba(0,0,0,0.2)', lineColorReversed: 'rgba(255,255,255,0.4)', diff --git a/src/core_plugins/metrics/public/visualizations/lib/create_legend_series.js b/src/core_plugins/metrics/public/visualizations/lib/create_legend_series.js index 5f3beb38f93358..eb4a9aab38b0df 100644 --- a/src/core_plugins/metrics/public/visualizations/lib/create_legend_series.js +++ b/src/core_plugins/metrics/public/visualizations/lib/create_legend_series.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import _ from 'lodash'; export default props => (row, i) => { @@ -17,6 +36,7 @@ export default props => (row, i) => {
+ +
+ +
+ +
+
+
diff --git a/src/ui/public/agg_types/index.js b/src/ui/public/agg_types/index.js index 818754b15d6fbc..89896727239275 100644 --- a/src/ui/public/agg_types/index.js +++ b/src/ui/public/agg_types/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import '../directives/validate_agg'; import './agg_params'; import { IndexedArray } from '../indexed_array'; diff --git a/src/ui/public/agg_types/metrics/avg.js b/src/ui/public/agg_types/metrics/avg.js index 8b29aaead0e151..9383ff54344e7f 100644 --- a/src/ui/public/agg_types/metrics/avg.js +++ b/src/ui/public/agg_types/metrics/avg.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; export const avgMetricAgg = new MetricAggType({ diff --git a/src/ui/public/agg_types/metrics/bucket_avg.js b/src/ui/public/agg_types/metrics/bucket_avg.js index 5e0899932faf11..98b53a41147d59 100644 --- a/src/ui/public/agg_types/metrics/bucket_avg.js +++ b/src/ui/public/agg_types/metrics/bucket_avg.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { get } from 'lodash'; import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; diff --git a/src/ui/public/agg_types/metrics/bucket_max.js b/src/ui/public/agg_types/metrics/bucket_max.js index 2959c449e13458..aa3badc25b0501 100644 --- a/src/ui/public/agg_types/metrics/bucket_max.js +++ b/src/ui/public/agg_types/metrics/bucket_max.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; diff --git a/src/ui/public/agg_types/metrics/bucket_min.js b/src/ui/public/agg_types/metrics/bucket_min.js index 1edae1f4e2c73c..dd2fa3e6b16383 100644 --- a/src/ui/public/agg_types/metrics/bucket_min.js +++ b/src/ui/public/agg_types/metrics/bucket_min.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; diff --git a/src/ui/public/agg_types/metrics/bucket_sum.js b/src/ui/public/agg_types/metrics/bucket_sum.js index cd5e36af2094c8..9eec111a88bb2e 100644 --- a/src/ui/public/agg_types/metrics/bucket_sum.js +++ b/src/ui/public/agg_types/metrics/bucket_sum.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; diff --git a/src/ui/public/agg_types/metrics/cardinality.js b/src/ui/public/agg_types/metrics/cardinality.js index 62523ebd5691c4..6c437c91fd6889 100644 --- a/src/ui/public/agg_types/metrics/cardinality.js +++ b/src/ui/public/agg_types/metrics/cardinality.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; import { fieldFormats } from '../../registry/field_formats'; diff --git a/src/ui/public/agg_types/metrics/count.js b/src/ui/public/agg_types/metrics/count.js index 5aea5547cd016a..6e45ce89399f37 100644 --- a/src/ui/public/agg_types/metrics/count.js +++ b/src/ui/public/agg_types/metrics/count.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; import { fieldFormats } from '../../registry/field_formats'; diff --git a/src/ui/public/agg_types/metrics/cumulative_sum.js b/src/ui/public/agg_types/metrics/cumulative_sum.js index f76b97b1a1e271..a1e077d995a480 100644 --- a/src/ui/public/agg_types/metrics/cumulative_sum.js +++ b/src/ui/public/agg_types/metrics/cumulative_sum.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; diff --git a/src/ui/public/agg_types/metrics/derivative.js b/src/ui/public/agg_types/metrics/derivative.js index 0bff9d1f49f54d..3221b3ac192a9b 100644 --- a/src/ui/public/agg_types/metrics/derivative.js +++ b/src/ui/public/agg_types/metrics/derivative.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; diff --git a/src/ui/public/agg_types/metrics/geo_bounds.js b/src/ui/public/agg_types/metrics/geo_bounds.js index 91c4fb80f02505..8d0212de40aa79 100644 --- a/src/ui/public/agg_types/metrics/geo_bounds.js +++ b/src/ui/public/agg_types/metrics/geo_bounds.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; export const geoBoundsMetricAgg = new MetricAggType({ diff --git a/src/ui/public/agg_types/metrics/geo_centroid.js b/src/ui/public/agg_types/metrics/geo_centroid.js index 6f0de616c855be..64e89d9c4aadfb 100644 --- a/src/ui/public/agg_types/metrics/geo_centroid.js +++ b/src/ui/public/agg_types/metrics/geo_centroid.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; export const geoCentroidMetricAgg = new MetricAggType({ diff --git a/src/ui/public/agg_types/metrics/get_response_agg_config_class.js b/src/ui/public/agg_types/metrics/get_response_agg_config_class.js index 67fbe1e987c4e3..af53fb4dadd027 100644 --- a/src/ui/public/agg_types/metrics/get_response_agg_config_class.js +++ b/src/ui/public/agg_types/metrics/get_response_agg_config_class.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; /** diff --git a/src/ui/public/agg_types/metrics/lib/make_nested_label.js b/src/ui/public/agg_types/metrics/lib/make_nested_label.js index c9a99f9f03515d..83b3fa85a6d639 100644 --- a/src/ui/public/agg_types/metrics/lib/make_nested_label.js +++ b/src/ui/public/agg_types/metrics/lib/make_nested_label.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; const makeNestedLabel = function (aggConfig, label) { diff --git a/src/ui/public/agg_types/metrics/lib/nested_agg_helpers.js b/src/ui/public/agg_types/metrics/lib/nested_agg_helpers.js index 4eda3af4488099..363361e76e9828 100644 --- a/src/ui/public/agg_types/metrics/lib/nested_agg_helpers.js +++ b/src/ui/public/agg_types/metrics/lib/nested_agg_helpers.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Forwards modifyAggConfigOnSearchRequestStart calls to a nested AggConfig. * This must be used for each parameter, that accepts a nested aggregation, otherwise diff --git a/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_controller.js b/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_controller.js index d076b5b614ee1f..ddd642b463fe6e 100644 --- a/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_controller.js +++ b/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { safeMakeLabel } from './safe_make_label'; diff --git a/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_helper.js b/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_helper.js index b98be6fc8d5edd..66dae6a70bf0ab 100644 --- a/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_helper.js +++ b/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_helper.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import metricAggTemplate from '../../controls/sub_agg.html'; import _ from 'lodash'; import { AggConfig } from '../../../vis/agg_config'; diff --git a/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_writter.js b/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_writter.js index b5e49b3373720c..645f7d69b0c9c7 100644 --- a/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_writter.js +++ b/src/ui/public/agg_types/metrics/lib/parent_pipeline_agg_writter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const parentPipelineAggWritter = function (agg, output) { const vis = agg.vis; const selectedMetric = agg.params.customMetric || vis.aggs.getResponseAggById(agg.params.metricAgg); diff --git a/src/ui/public/agg_types/metrics/lib/safe_make_label.js b/src/ui/public/agg_types/metrics/lib/safe_make_label.js index b7f346ed5ae934..4d5794142ed573 100644 --- a/src/ui/public/agg_types/metrics/lib/safe_make_label.js +++ b/src/ui/public/agg_types/metrics/lib/safe_make_label.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const safeMakeLabel = function (agg) { try { return agg.makeLabel(); diff --git a/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_controller.js b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_controller.js index b3160c70ebfb56..3704829fdcbb7f 100644 --- a/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_controller.js +++ b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { safeMakeLabel } from './safe_make_label'; const siblingPipelineAggController = function (type) { diff --git a/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_helper.js b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_helper.js index 1c65cc63151158..4c8f72df68c0a2 100644 --- a/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_helper.js +++ b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_helper.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { AggConfig } from '../../../vis/agg_config'; import { Schemas } from '../../../vis/editors/default/schemas'; diff --git a/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_writter.js b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_writter.js index 2b7b51f64d059c..bc8d957bbeae5c 100644 --- a/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_writter.js +++ b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_writter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const siblingPipelineAggWritter = function (agg, output) { if (!agg.params.customMetric) return; diff --git a/src/ui/public/agg_types/metrics/max.js b/src/ui/public/agg_types/metrics/max.js index 7d1a712a3e250e..dc97d34a5a5538 100644 --- a/src/ui/public/agg_types/metrics/max.js +++ b/src/ui/public/agg_types/metrics/max.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; export const maxMetricAgg = new MetricAggType({ diff --git a/src/ui/public/agg_types/metrics/median.js b/src/ui/public/agg_types/metrics/median.js index aa82fc13f78e63..bf904516e38c6e 100644 --- a/src/ui/public/agg_types/metrics/median.js +++ b/src/ui/public/agg_types/metrics/median.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; import { percentilesMetricAgg } from './percentiles'; diff --git a/src/ui/public/agg_types/metrics/metric_agg_type.js b/src/ui/public/agg_types/metrics/metric_agg_type.js index 2db682458cfb53..49a04ef16eee10 100644 --- a/src/ui/public/agg_types/metrics/metric_agg_type.js +++ b/src/ui/public/agg_types/metrics/metric_agg_type.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { AggType } from '../agg_type'; import { fieldFormats } from '../../registry/field_formats'; diff --git a/src/ui/public/agg_types/metrics/min.js b/src/ui/public/agg_types/metrics/min.js index e415e0223d82fe..89753713482f59 100644 --- a/src/ui/public/agg_types/metrics/min.js +++ b/src/ui/public/agg_types/metrics/min.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; export const minMetricAgg = new MetricAggType({ diff --git a/src/ui/public/agg_types/metrics/moving_avg.js b/src/ui/public/agg_types/metrics/moving_avg.js index c6bb93c0c646bb..8dbad85a215767 100644 --- a/src/ui/public/agg_types/metrics/moving_avg.js +++ b/src/ui/public/agg_types/metrics/moving_avg.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; diff --git a/src/ui/public/agg_types/metrics/percentile_ranks.js b/src/ui/public/agg_types/metrics/percentile_ranks.js index bd52884c12bf5d..8c696fc9a504ec 100644 --- a/src/ui/public/agg_types/metrics/percentile_ranks.js +++ b/src/ui/public/agg_types/metrics/percentile_ranks.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import valuesEditor from '../controls/percentile_ranks.html'; import '../../number_list'; import { MetricAggType } from './metric_agg_type'; diff --git a/src/ui/public/agg_types/metrics/percentiles.js b/src/ui/public/agg_types/metrics/percentiles.js index 5ec2bd9f0e45e5..0ab7b109064511 100644 --- a/src/ui/public/agg_types/metrics/percentiles.js +++ b/src/ui/public/agg_types/metrics/percentiles.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { ordinalSuffix } from '../../utils/ordinal_suffix'; import percentsEditor from '../controls/percentiles.html'; import '../../number_list'; diff --git a/src/ui/public/agg_types/metrics/percentiles_get_value.js b/src/ui/public/agg_types/metrics/percentiles_get_value.js index bcf086bf81a689..33015190f5470c 100644 --- a/src/ui/public/agg_types/metrics/percentiles_get_value.js +++ b/src/ui/public/agg_types/metrics/percentiles_get_value.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { find } from 'lodash'; export function getPercentileValue(agg, bucket) { diff --git a/src/ui/public/agg_types/metrics/serial_diff.js b/src/ui/public/agg_types/metrics/serial_diff.js index adfd11661986ea..0716d7643e4fd6 100644 --- a/src/ui/public/agg_types/metrics/serial_diff.js +++ b/src/ui/public/agg_types/metrics/serial_diff.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; diff --git a/src/ui/public/agg_types/metrics/std_deviation.js b/src/ui/public/agg_types/metrics/std_deviation.js index ddf70f1e1ba9c1..244d840c42c019 100644 --- a/src/ui/public/agg_types/metrics/std_deviation.js +++ b/src/ui/public/agg_types/metrics/std_deviation.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { MetricAggType } from './metric_agg_type'; import { getResponseAggConfigClass } from './get_response_agg_config_class'; diff --git a/src/ui/public/agg_types/metrics/sum.js b/src/ui/public/agg_types/metrics/sum.js index dc9ed8a0efe65e..edcb6d4756296c 100644 --- a/src/ui/public/agg_types/metrics/sum.js +++ b/src/ui/public/agg_types/metrics/sum.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MetricAggType } from './metric_agg_type'; export const sumMetricAgg = new MetricAggType({ diff --git a/src/ui/public/agg_types/metrics/top_hit.js b/src/ui/public/agg_types/metrics/top_hit.js index d844087ad12ebb..a28b0e56426df4 100644 --- a/src/ui/public/agg_types/metrics/top_hit.js +++ b/src/ui/public/agg_types/metrics/top_hit.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { MetricAggType } from './metric_agg_type'; import topSortEditor from '../controls/top_sort.html'; diff --git a/src/ui/public/agg_types/param_types/base.js b/src/ui/public/agg_types/param_types/base.js index b795b6ae4b761d..39085cd2ed18a4 100644 --- a/src/ui/public/agg_types/param_types/base.js +++ b/src/ui/public/agg_types/param_types/base.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; function BaseParamType(config) { diff --git a/src/ui/public/agg_types/param_types/field.js b/src/ui/public/agg_types/param_types/field.js index 9d5d35c45e68b4..e2748d45261e10 100644 --- a/src/ui/public/agg_types/param_types/field.js +++ b/src/ui/public/agg_types/param_types/field.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { SavedObjectNotFound } from '../../errors'; import _ from 'lodash'; import editorHtml from '../controls/field.html'; diff --git a/src/ui/public/agg_types/param_types/json.js b/src/ui/public/agg_types/param_types/json.js index 152a5287c75856..6eb7e8662b6297 100644 --- a/src/ui/public/agg_types/param_types/json.js +++ b/src/ui/public/agg_types/param_types/json.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import editorHtml from '../controls/raw_json.html'; import { BaseParamType } from './base'; diff --git a/src/ui/public/agg_types/param_types/optioned.js b/src/ui/public/agg_types/param_types/optioned.js index 6589f1b0946692..a02165b06c4c87 100644 --- a/src/ui/public/agg_types/param_types/optioned.js +++ b/src/ui/public/agg_types/param_types/optioned.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { IndexedArray } from '../../indexed_array'; import { BaseParamType } from './base'; import { createLegacyClass } from '../../utils/legacy_class'; diff --git a/src/ui/public/agg_types/param_types/regex.js b/src/ui/public/agg_types/param_types/regex.js index a4cbac16037677..2ac014b4961202 100644 --- a/src/ui/public/agg_types/param_types/regex.js +++ b/src/ui/public/agg_types/param_types/regex.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import editorHtml from '../controls/regular_expression.html'; import { BaseParamType } from './base'; diff --git a/src/ui/public/agg_types/param_types/string.js b/src/ui/public/agg_types/param_types/string.js index 7656b63bfb343e..68c7c3aa4bfd58 100644 --- a/src/ui/public/agg_types/param_types/string.js +++ b/src/ui/public/agg_types/param_types/string.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import editorHtml from '../controls/string.html'; import { BaseParamType } from './base'; import { createLegacyClass } from '../../utils/legacy_class'; diff --git a/src/ui/public/autoload/accessibility.js b/src/ui/public/autoload/accessibility.js index 7d2642c61e1799..1c846177eca872 100644 --- a/src/ui/public/autoload/accessibility.js +++ b/src/ui/public/autoload/accessibility.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import '../accessibility'; diff --git a/src/ui/public/autoload/all.js b/src/ui/public/autoload/all.js index 12951c84346e79..fba21aacd19848 100644 --- a/src/ui/public/autoload/all.js +++ b/src/ui/public/autoload/all.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './accessibility'; import './modules'; import './directives'; diff --git a/src/ui/public/autoload/directives.js b/src/ui/public/autoload/directives.js index 3908c3e116de1f..c31f62e8db6b4b 100644 --- a/src/ui/public/autoload/directives.js +++ b/src/ui/public/autoload/directives.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const context = require.context('../directives', false, /[\/\\](?!\.|_)[^\/\\]+\.js/); context.keys().forEach(key => context(key)); diff --git a/src/ui/public/autoload/filters.js b/src/ui/public/autoload/filters.js index 583d1dcead0721..ccdf784044958c 100644 --- a/src/ui/public/autoload/filters.js +++ b/src/ui/public/autoload/filters.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const context = require.context('../filters', false, /[\/\\](?!\.|_)[^\/\\]+\.js/); context.keys().forEach(key => context(key)); diff --git a/src/ui/public/autoload/modules.js b/src/ui/public/autoload/modules.js index a0661cb97b1ba0..194279dfd05bf9 100644 --- a/src/ui/public/autoload/modules.js +++ b/src/ui/public/autoload/modules.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import 'angular'; import '../chrome'; import '../bind'; diff --git a/src/ui/public/autoload/styles.js b/src/ui/public/autoload/styles.js index abc05918fb69d6..df9e05e6d71c52 100644 --- a/src/ui/public/autoload/styles.js +++ b/src/ui/public/autoload/styles.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const theme = require('../theme'); // Kibana UI Framework diff --git a/src/ui/public/bind/__tests__/bind.js b/src/ui/public/bind/__tests__/bind.js index 4d11e0dabb4639..ce59076df923d6 100644 --- a/src/ui/public/bind/__tests__/bind.js +++ b/src/ui/public/bind/__tests__/bind.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; describe('$scope.$bind', function () { diff --git a/src/ui/public/bind/bind.js b/src/ui/public/bind/bind.js index 275f591a856527..42b090532c5d94 100644 --- a/src/ui/public/bind/bind.js +++ b/src/ui/public/bind/bind.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import { uiModules } from '../modules'; diff --git a/src/ui/public/bind/index.js b/src/ui/public/bind/index.js index fd956c1e2a1a3f..d542452d1a80f5 100644 --- a/src/ui/public/bind/index.js +++ b/src/ui/public/bind/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './bind'; diff --git a/src/ui/public/binder/__tests__/binder.js b/src/ui/public/binder/__tests__/binder.js index a862259ecdf12e..3a0ddff2137a40 100644 --- a/src/ui/public/binder/__tests__/binder.js +++ b/src/ui/public/binder/__tests__/binder.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/binder/binder.js b/src/ui/public/binder/binder.js index fe9930388b3448..ebb0d43f55be4a 100644 --- a/src/ui/public/binder/binder.js +++ b/src/ui/public/binder/binder.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import $ from 'jquery'; diff --git a/src/ui/public/binder/index.js b/src/ui/public/binder/index.js index 61cb7a92d315c0..ce91a987fa570a 100644 --- a/src/ui/public/binder/index.js +++ b/src/ui/public/binder/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { Binder } from './binder'; diff --git a/src/ui/public/bound_to_config_obj.js b/src/ui/public/bound_to_config_obj.js index 8ed38bde803c9b..307345d62ea168 100644 --- a/src/ui/public/bound_to_config_obj.js +++ b/src/ui/public/bound_to_config_obj.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function BoundToConfigObjProvider(config) { diff --git a/src/ui/public/check_box/check_box.js b/src/ui/public/check_box/check_box.js index 900b812ca4af19..2c1f814963a77f 100644 --- a/src/ui/public/check_box/check_box.js +++ b/src/ui/public/check_box/check_box.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; import template from './check_box.html'; diff --git a/src/ui/public/check_box/index.js b/src/ui/public/check_box/index.js index 54c21f29fb655d..f9d353d7485017 100644 --- a/src/ui/public/check_box/index.js +++ b/src/ui/public/check_box/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './check_box'; diff --git a/src/ui/public/chrome/__tests__/kbn_loading_indicator.js b/src/ui/public/chrome/__tests__/kbn_loading_indicator.js deleted file mode 100644 index 30594a05fdb2aa..00000000000000 --- a/src/ui/public/chrome/__tests__/kbn_loading_indicator.js +++ /dev/null @@ -1,35 +0,0 @@ -import ngMock from 'ng_mock'; -import expect from 'expect.js'; -import $ from 'jquery'; - -import '../directives/loading_indicator/loading_indicator'; - -describe('kbnLoadingIndicator', function () { - let compile; - - beforeEach(() => { - ngMock.module('kibana'); - ngMock.inject(function ($compile, $rootScope) { - compile = function (hasActiveConnections) { - $rootScope.chrome = { - httpActive: hasActiveConnections ? [1] : [] - }; - const $el = $(''); - $compile($el)($rootScope); - $rootScope.$apply(); - return $el; - }; - }); - - }); - - it(`doesn't have ng-hide class when there are connections`, function () { - const $el = compile(true); - expect($el.hasClass('ng-hide')).to.be(false); - }); - - it('has ng-hide class when there are no connections', function () { - const $el = compile(false); - expect($el.hasClass('ng-hide')).to.be(true); - }); -}); diff --git a/src/ui/public/chrome/__tests__/nav_controls.js b/src/ui/public/chrome/__tests__/nav_controls.js index 6b863b5390000d..cf664b943190c6 100644 --- a/src/ui/public/chrome/__tests__/nav_controls.js +++ b/src/ui/public/chrome/__tests__/nav_controls.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import $ from 'jquery'; import expect from 'expect.js'; diff --git a/src/ui/public/chrome/api/__tests__/angular.js b/src/ui/public/chrome/api/__tests__/angular.js index c9ad957135fbcc..ed2ccb41a57e27 100644 --- a/src/ui/public/chrome/api/__tests__/angular.js +++ b/src/ui/public/chrome/api/__tests__/angular.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { initAngularApi } from '../angular'; import { noop } from 'lodash'; diff --git a/src/ui/public/chrome/api/__tests__/apps.js b/src/ui/public/chrome/api/__tests__/apps.js index 613920e0dcb867..a68dbfb323de5a 100644 --- a/src/ui/public/chrome/api/__tests__/apps.js +++ b/src/ui/public/chrome/api/__tests__/apps.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import setup from '../apps'; diff --git a/src/ui/public/chrome/api/__tests__/nav.js b/src/ui/public/chrome/api/__tests__/nav.js index 36b589d45fb0cc..ac6a9d961b77f2 100644 --- a/src/ui/public/chrome/api/__tests__/nav.js +++ b/src/ui/public/chrome/api/__tests__/nav.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { initChromeNavApi } from '../nav'; diff --git a/src/ui/public/chrome/api/__tests__/xsrf.js b/src/ui/public/chrome/api/__tests__/xsrf.js index 97bfebaa88c6a7..8d5cbd7e4e37f6 100644 --- a/src/ui/public/chrome/api/__tests__/xsrf.js +++ b/src/ui/public/chrome/api/__tests__/xsrf.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import expect from 'expect.js'; import sinon from 'sinon'; @@ -9,7 +28,7 @@ import { version } from '../../../../../../package.json'; const xsrfHeader = 'kbn-version'; describe('chrome xsrf apis', function () { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); afterEach(function () { sandbox.restore(); diff --git a/src/ui/public/chrome/api/angular.js b/src/ui/public/chrome/api/angular.js index e2aef18f78fbca..3de4aae1109f68 100644 --- a/src/ui/public/chrome/api/angular.js +++ b/src/ui/public/chrome/api/angular.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { format as formatUrl, parse as parseUrl } from 'url'; @@ -31,6 +50,13 @@ export function initAngularApi(chrome, internals) { a.href = chrome.addBasePath('/elasticsearch'); return a.href; }())) + .config($locationProvider => { + $locationProvider.html5Mode({ + enabled: false, + requireBase: false, + rewriteLinks: false, + }); + }) .config(chrome.$setupXsrfRequestInterceptor) .config(function ($compileProvider, $locationProvider) { if (!internals.devMode) { @@ -39,6 +65,7 @@ export function initAngularApi(chrome, internals) { $locationProvider.hashPrefix(''); }) + .run(internals.capture$httpLoadingCount) .run(($location, $rootScope, Private, config) => { chrome.getFirstPathSegment = () => { return $location.path().split('/')[1]; diff --git a/src/ui/public/chrome/api/apps.js b/src/ui/public/chrome/api/apps.js index a2c8f4b57bb8fb..26f14941e73d3e 100644 --- a/src/ui/public/chrome/api/apps.js +++ b/src/ui/public/chrome/api/apps.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { clone, get } from 'lodash'; import { resolve } from 'url'; diff --git a/src/ui/public/chrome/api/controls.js b/src/ui/public/chrome/api/controls.js index c2d0068cac2006..a8dde867c371f0 100644 --- a/src/ui/public/chrome/api/controls.js +++ b/src/ui/public/chrome/api/controls.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; // eslint-disable-next-line @elastic/kibana-custom/no-default-export diff --git a/src/ui/public/chrome/api/loading_count.js b/src/ui/public/chrome/api/loading_count.js new file mode 100644 index 00000000000000..9bd3d659a4df5e --- /dev/null +++ b/src/ui/public/chrome/api/loading_count.js @@ -0,0 +1,92 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { isSystemApiRequest } from '../../system_api'; + +export function initLoadingCountApi(chrome, internals) { + const counts = { angular: 0, manual: 0 }; + const handlers = new Set(); + + function getCount() { + return counts.angular + counts.manual; + } + + // update counts and call handlers with sum if there is a change + function update(name, count) { + if (counts[name] === count) { + return; + } + + counts[name] = count; + for (const handler of handlers) { + handler(getCount()); + } + } + + /** + * Injected into angular module by ui/chrome angular integration + * and adds a root-level watcher that will capture the count of + * active $http requests on each digest loop + * @param {Angular.Scope} $rootScope + * @param {HttpService} $http + * @return {undefined} + */ + internals.capture$httpLoadingCount = function ($rootScope, $http) { + $rootScope.$watch(() => { + const reqs = $http.pendingRequests || []; + update('angular', reqs.filter(req => !isSystemApiRequest(req)).length); + }); + }; + + chrome.loadingCount = new class ChromeLoadingCountApi { + /** + * Call to add a subscriber to for the loading count that + * will be called every time the loading count changes. + * + * @type {Observable} + * @return {Function} unsubscribe + */ + subscribe(handler) { + handlers.add(handler); + + // send the current count to the handler + handler(getCount()); + + return () => { + handlers.delete(handler); + }; + } + + /** + * Increment the loading count by one + * @return {undefined} + */ + increment() { + update('manual', counts.manual + 1); + } + + /** + * Decrement the loading count by one + * @return {undefined} + */ + decrement() { + update('manual', counts.manual - 1); + } + }; +} diff --git a/src/ui/public/chrome/api/nav.js b/src/ui/public/chrome/api/nav.js index c1d0ceea932758..5163c083d3013d 100644 --- a/src/ui/public/chrome/api/nav.js +++ b/src/ui/public/chrome/api/nav.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { remove } from 'lodash'; import { prependPath } from '../../url/prepend_path'; import { relativeToAbsolute } from '../../url/relative_to_absolute'; diff --git a/src/ui/public/chrome/api/template.js b/src/ui/public/chrome/api/template.js index 12d28b452e74b7..d1295dc8dddaa1 100644 --- a/src/ui/public/chrome/api/template.js +++ b/src/ui/public/chrome/api/template.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // eslint-disable-next-line @elastic/kibana-custom/no-default-export export default function (chrome, internals) { diff --git a/src/ui/public/chrome/api/theme.js b/src/ui/public/chrome/api/theme.js index d3f45e5a56e27f..15c4e1f8602624 100644 --- a/src/ui/public/chrome/api/theme.js +++ b/src/ui/public/chrome/api/theme.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; // eslint-disable-next-line @elastic/kibana-custom/no-default-export diff --git a/src/ui/public/chrome/api/translations.js b/src/ui/public/chrome/api/translations.js index a9921d057dc407..589565a46e98e5 100644 --- a/src/ui/public/chrome/api/translations.js +++ b/src/ui/public/chrome/api/translations.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // eslint-disable-next-line @elastic/kibana-custom/no-default-export export default function (chrome, internals) { /** diff --git a/src/ui/public/chrome/api/ui_settings.js b/src/ui/public/chrome/api/ui_settings.js index d54828eee1ff1a..e602c67f0e57fd 100644 --- a/src/ui/public/chrome/api/ui_settings.js +++ b/src/ui/public/chrome/api/ui_settings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { metadata } from '../../metadata'; import { Notifier } from '../../notify'; import { UiSettingsClient } from '../../../ui_settings/public/ui_settings_client'; diff --git a/src/ui/public/chrome/api/xsrf.js b/src/ui/public/chrome/api/xsrf.js index db55043dd4ddeb..ac59d6367aeae8 100644 --- a/src/ui/public/chrome/api/xsrf.js +++ b/src/ui/public/chrome/api/xsrf.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import { set } from 'lodash'; diff --git a/src/ui/public/chrome/chrome.js b/src/ui/public/chrome/chrome.js index fb23f6ffcbd65f..cfcefadc67bba1 100644 --- a/src/ui/public/chrome/chrome.js +++ b/src/ui/public/chrome/chrome.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import angular from 'angular'; @@ -23,6 +42,7 @@ import themeApi from './api/theme'; import translationsApi from './api/translations'; import { initChromeXsrfApi } from './api/xsrf'; import { initUiSettingsApi } from './api/ui_settings'; +import { initLoadingCountApi } from './api/loading_count'; export const chrome = {}; const internals = _.defaults( @@ -44,6 +64,7 @@ initUiSettingsApi(chrome); appsApi(chrome, internals); initChromeXsrfApi(chrome, internals); initChromeNavApi(chrome, internals); +initLoadingCountApi(chrome, internals); initAngularApi(chrome, internals); controlsApi(chrome, internals); templateApi(chrome, internals); @@ -52,6 +73,12 @@ translationsApi(chrome, internals); const waitForBootstrap = new Promise(resolve => { chrome.bootstrap = function () { + // import chrome nav controls and hacks now so that they are executed after + // everything else, can safely import the chrome, and interact with services + // and such setup by all other modules + require('uiExports/chromeNavControls'); + require('uiExports/hacks'); + chrome.setupAngular(); angular.bootstrap(document.body, ['kibana']); resolve(); diff --git a/src/ui/public/chrome/directives/__snapshots__/loading_indicator.test.js.snap b/src/ui/public/chrome/directives/__snapshots__/loading_indicator.test.js.snap new file mode 100644 index 00000000000000..301e34bb420504 --- /dev/null +++ b/src/ui/public/chrome/directives/__snapshots__/loading_indicator.test.js.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`kbnLoadingIndicator is hidden by default 1`] = ` +
+
+
+`; + +exports[`kbnLoadingIndicator is visible when loadingCount is > 0 1`] = ` +
+
+
+`; diff --git a/src/ui/public/chrome/directives/__tests__/sub_url_route_filter.js b/src/ui/public/chrome/directives/__tests__/sub_url_route_filter.js index e4b27b5059950c..fc411b5638b3b1 100644 --- a/src/ui/public/chrome/directives/__tests__/sub_url_route_filter.js +++ b/src/ui/public/chrome/directives/__tests__/sub_url_route_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/chrome/directives/append_nav_controls.js b/src/ui/public/chrome/directives/append_nav_controls.js index 471c483848e6ee..f4f3ee7d122bae 100644 --- a/src/ui/public/chrome/directives/append_nav_controls.js +++ b/src/ui/public/chrome/directives/append_nav_controls.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { chromeNavControlsRegistry } from '../../registry/chrome_nav_controls'; import { uiModules } from '../../modules'; diff --git a/src/ui/public/chrome/directives/global_nav/app_switcher/__tests__/app_switcher.js b/src/ui/public/chrome/directives/global_nav/app_switcher/__tests__/app_switcher.js index aa37dbe0aa8ead..bce7b47441f827 100644 --- a/src/ui/public/chrome/directives/global_nav/app_switcher/__tests__/app_switcher.js +++ b/src/ui/public/chrome/directives/global_nav/app_switcher/__tests__/app_switcher.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/chrome/directives/global_nav/app_switcher/app_switcher.js b/src/ui/public/chrome/directives/global_nav/app_switcher/app_switcher.js index 591618858bc2ce..b349435da17c9f 100644 --- a/src/ui/public/chrome/directives/global_nav/app_switcher/app_switcher.js +++ b/src/ui/public/chrome/directives/global_nav/app_switcher/app_switcher.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { DomLocationProvider } from '../../../../dom_location'; import { parse } from 'url'; import { uiModules } from '../../../../modules'; diff --git a/src/ui/public/chrome/directives/global_nav/app_switcher/index.js b/src/ui/public/chrome/directives/global_nav/app_switcher/index.js index 634ac427df3f12..e4608515d024cd 100644 --- a/src/ui/public/chrome/directives/global_nav/app_switcher/index.js +++ b/src/ui/public/chrome/directives/global_nav/app_switcher/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './app_switcher'; diff --git a/src/ui/public/chrome/directives/global_nav/global_nav.js b/src/ui/public/chrome/directives/global_nav/global_nav.js index b934abc1347862..7abf81971b7b0a 100644 --- a/src/ui/public/chrome/directives/global_nav/global_nav.js +++ b/src/ui/public/chrome/directives/global_nav/global_nav.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './app_switcher'; import './global_nav_link'; diff --git a/src/ui/public/chrome/directives/global_nav/global_nav_link/__tests__/global_nav_link.js b/src/ui/public/chrome/directives/global_nav/global_nav_link/__tests__/global_nav_link.js index bf67d983fa7d5b..d265df874216dd 100644 --- a/src/ui/public/chrome/directives/global_nav/global_nav_link/__tests__/global_nav_link.js +++ b/src/ui/public/chrome/directives/global_nav/global_nav_link/__tests__/global_nav_link.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/chrome/directives/global_nav/global_nav_link/global_nav_link.js b/src/ui/public/chrome/directives/global_nav/global_nav_link/global_nav_link.js index c5d1e05d9c63fa..437bec461ba6ce 100644 --- a/src/ui/public/chrome/directives/global_nav/global_nav_link/global_nav_link.js +++ b/src/ui/public/chrome/directives/global_nav/global_nav_link/global_nav_link.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import globalNavLinkTemplate from './global_nav_link.html'; import './global_nav_link.less'; diff --git a/src/ui/public/chrome/directives/global_nav/global_nav_link/index.js b/src/ui/public/chrome/directives/global_nav/global_nav_link/index.js index 2e29dd52bdb663..b485c2302d13bc 100644 --- a/src/ui/public/chrome/directives/global_nav/global_nav_link/index.js +++ b/src/ui/public/chrome/directives/global_nav/global_nav_link/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './global_nav_link'; diff --git a/src/ui/public/chrome/directives/global_nav/index.js b/src/ui/public/chrome/directives/global_nav/index.js index 49e5dcfa431a37..60b503f2dceda5 100644 --- a/src/ui/public/chrome/directives/global_nav/index.js +++ b/src/ui/public/chrome/directives/global_nav/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './global_nav'; diff --git a/src/ui/public/chrome/directives/index.js b/src/ui/public/chrome/directives/index.js index d4c4cd1956c597..0cd8d49c0c31a2 100644 --- a/src/ui/public/chrome/directives/index.js +++ b/src/ui/public/chrome/directives/index.js @@ -1,9 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './global_nav'; import { kbnChromeProvider } from './kbn_chrome'; import { kbnAppendChromeNavControls } from './append_nav_controls'; -import './loading_indicator/loading_indicator'; +import './loading_indicator'; export function directivesProvider(chrome, internals) { kbnChromeProvider(chrome, internals); diff --git a/src/ui/public/chrome/directives/kbn_chrome.js b/src/ui/public/chrome/directives/kbn_chrome.js index d4b053df04d38a..1f1b03df53bdd2 100644 --- a/src/ui/public/chrome/directives/kbn_chrome.js +++ b/src/ui/public/chrome/directives/kbn_chrome.js @@ -1,11 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import ReactDOM from 'react-dom'; import $ from 'jquery'; -import { remove } from 'lodash'; import './kbn_chrome.less'; import { uiModules } from '../../modules'; -import { isSystemApiRequest } from '../../system_api'; import { getUnhashableStatesProvider, unhashUrl, @@ -68,13 +85,6 @@ export function kbnChromeProvider(chrome, internals) { $rootScope.$on('$routeUpdate', onRouteChange); updateSubUrls(); // initialize sub urls - const allPendingHttpRequests = () => $http.pendingRequests; - const removeSystemApiRequests = (pendingHttpRequests = []) => remove(pendingHttpRequests, isSystemApiRequest); - $scope.$watchCollection(allPendingHttpRequests, removeSystemApiRequests); - - // and some local values - chrome.httpActive = $http.pendingRequests; - // Notifications $scope.notifList = notify._notifs; diff --git a/src/ui/public/chrome/directives/kbn_chrome.less b/src/ui/public/chrome/directives/kbn_chrome.less index 348f256d52119f..7103decdbbec5a 100644 --- a/src/ui/public/chrome/directives/kbn_chrome.less +++ b/src/ui/public/chrome/directives/kbn_chrome.less @@ -8,7 +8,8 @@ body { } .app-wrapper { - .real-flex-parent(); + display: flex; + flex-flow: column nowrap; position: absolute; left: @global-nav-closed-width; top: 0; @@ -31,6 +32,14 @@ body { } } - .app-wrapper-panel { - .flex-parent(@shrink: 0); +.app-wrapper-panel { + display: flex; + flex-grow: 1; + flex-shrink: 0; + flex-basis: auto; + flex-direction: column; + + > * { + flex-shrink: 0; } +} diff --git a/src/ui/public/chrome/directives/loading_indicator.js b/src/ui/public/chrome/directives/loading_indicator.js new file mode 100644 index 00000000000000..f8f6c671683f58 --- /dev/null +++ b/src/ui/public/chrome/directives/loading_indicator.js @@ -0,0 +1,67 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import 'ngreact'; +import React from 'react'; +import classNames from 'classnames'; + +import { uiModules } from 'ui/modules'; +import chrome from 'ui/chrome'; + +import './loading_indicator.less'; + +export class LoadingIndicator extends React.Component { + state = { + visible: false, + } + + componentDidMount() { + this._unsub = chrome.loadingCount.subscribe((count) => { + this.setState({ + visible: count > 0 + }); + }); + } + + componentWillUnmount() { + this._unsub(); + this._unsub = null; + } + + render() { + const className = classNames( + 'loadingIndicator', + this.state.visible ? null : 'hidden' + ); + + const testSubj = this.state.visible + ? 'globalLoadingIndicator' + : 'globalLoadingIndicator-hidden'; + + return ( +
+
+
+ ); + } +} + +uiModules + .get('app/kibana', ['react']) + .directive('kbnLoadingIndicator', reactDirective => reactDirective(LoadingIndicator)); diff --git a/src/ui/public/chrome/directives/loading_indicator/loading_indicator.less b/src/ui/public/chrome/directives/loading_indicator.less similarity index 98% rename from src/ui/public/chrome/directives/loading_indicator/loading_indicator.less rename to src/ui/public/chrome/directives/loading_indicator.less index 660b8a003c8d21..3571fe3e5fd674 100644 --- a/src/ui/public/chrome/directives/loading_indicator/loading_indicator.less +++ b/src/ui/public/chrome/directives/loading_indicator.less @@ -18,7 +18,7 @@ overflow: hidden; // 2 height: @loadingIndicatorHeight; - &.ng-hide { + &.hidden { visibility: hidden; opacity: 0; transition-delay: 0.25s; diff --git a/src/ui/public/chrome/directives/loading_indicator.test.js b/src/ui/public/chrome/directives/loading_indicator.test.js new file mode 100644 index 00000000000000..ddaab276443fe4 --- /dev/null +++ b/src/ui/public/chrome/directives/loading_indicator.test.js @@ -0,0 +1,57 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; +import chrome from 'ui/chrome'; + +import { LoadingIndicator } from './loading_indicator'; + +jest.mock('ui/chrome', () => { + return { + loadingCount: { + subscribe: jest.fn(() => { + return () => {}; + }) + } + }; +}); + +beforeEach(() => { + chrome.loadingCount.subscribe.mockClear(); +}); + +describe('kbnLoadingIndicator', function () { + it('is hidden by default', function () { + const wrapper = shallow(); + expect(wrapper.prop('data-test-subj')).toBe('globalLoadingIndicator-hidden'); + expect(wrapper).toMatchSnapshot(); + }); + + it('is visible when loadingCount is > 0', () => { + chrome.loadingCount.subscribe.mockImplementation((fn) => { + fn(1); + return () => {}; + }); + + const wrapper = shallow(); + expect(wrapper.prop('data-test-subj')).toBe('globalLoadingIndicator'); + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/src/ui/public/chrome/directives/loading_indicator/index.js b/src/ui/public/chrome/directives/loading_indicator/index.js deleted file mode 100644 index 25a4c3ea14759e..00000000000000 --- a/src/ui/public/chrome/directives/loading_indicator/index.js +++ /dev/null @@ -1 +0,0 @@ -import './loading_indicator'; diff --git a/src/ui/public/chrome/directives/loading_indicator/loading_indicator.html b/src/ui/public/chrome/directives/loading_indicator/loading_indicator.html deleted file mode 100644 index b21180fa32793b..00000000000000 --- a/src/ui/public/chrome/directives/loading_indicator/loading_indicator.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
-
diff --git a/src/ui/public/chrome/directives/loading_indicator/loading_indicator.js b/src/ui/public/chrome/directives/loading_indicator/loading_indicator.js deleted file mode 100644 index fe77f954d501d5..00000000000000 --- a/src/ui/public/chrome/directives/loading_indicator/loading_indicator.js +++ /dev/null @@ -1,13 +0,0 @@ -import { uiModules } from '../../../modules'; -import template from './loading_indicator.html'; -import './loading_indicator.less'; - -uiModules - .get('ui/kibana') - .directive('kbnLoadingIndicator', function () { - return { - restrict: 'E', - replace: true, - template, - }; - }); diff --git a/src/ui/public/chrome/directives/sub_url_route_filter.js b/src/ui/public/chrome/directives/sub_url_route_filter.js index ccfc68c834f670..0ccd10d97ad25c 100644 --- a/src/ui/public/chrome/directives/sub_url_route_filter.js +++ b/src/ui/public/chrome/directives/sub_url_route_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Creates a function that will be called on each route change * to determine if the event should be used to update the last diff --git a/src/ui/public/chrome/index.js b/src/ui/public/chrome/index.js index 1804ded62c31bb..ad62192704a1e8 100644 --- a/src/ui/public/chrome/index.js +++ b/src/ui/public/chrome/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { chrome } from './chrome'; // eslint-disable-next-line @elastic/kibana-custom/no-default-export diff --git a/src/ui/public/chrome/services/global_nav_state.js b/src/ui/public/chrome/services/global_nav_state.js index a9ba964adae91c..9f2131926c50a3 100644 --- a/src/ui/public/chrome/services/global_nav_state.js +++ b/src/ui/public/chrome/services/global_nav_state.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../../modules'; diff --git a/src/ui/public/chrome/services/index.js b/src/ui/public/chrome/services/index.js index 4bac1c4cc8cdd5..3b3967f51b2ffa 100644 --- a/src/ui/public/chrome/services/index.js +++ b/src/ui/public/chrome/services/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './global_nav_state'; diff --git a/src/ui/public/collapsible_sidebar/collapsible_sidebar.js b/src/ui/public/collapsible_sidebar/collapsible_sidebar.js index cbafcad929d59f..07f659448c9d74 100644 --- a/src/ui/public/collapsible_sidebar/collapsible_sidebar.js +++ b/src/ui/public/collapsible_sidebar/collapsible_sidebar.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './collapsible_sidebar.less'; import _ from 'lodash'; import $ from 'jquery'; diff --git a/src/ui/public/collapsible_sidebar/index.js b/src/ui/public/collapsible_sidebar/index.js index e10bdc590bfc61..9f818922f71360 100644 --- a/src/ui/public/collapsible_sidebar/index.js +++ b/src/ui/public/collapsible_sidebar/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './collapsible_sidebar'; diff --git a/src/ui/public/compat/index.js b/src/ui/public/compat/index.js index 16b9c361ebb84e..8988a7aba79413 100644 --- a/src/ui/public/compat/index.js +++ b/src/ui/public/compat/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { InitAfterBindingsWorkaround, callAfterBindingsWorkaround diff --git a/src/ui/public/compat/init_after_bindings_workaround.js b/src/ui/public/compat/init_after_bindings_workaround.js index bc21fe673a925e..23ee66a564e7e1 100644 --- a/src/ui/public/compat/init_after_bindings_workaround.js +++ b/src/ui/public/compat/init_after_bindings_workaround.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * WHAT NEEDS THIS WORKAROUND? * =========================== diff --git a/src/ui/public/config/__tests__/config.js b/src/ui/public/config/__tests__/config.js index 92ae1fa3b68ab2..05d2b4bb87c94f 100644 --- a/src/ui/public/config/__tests__/config.js +++ b/src/ui/public/config/__tests__/config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import sinon from 'sinon'; diff --git a/src/ui/public/config/config.js b/src/ui/public/config/config.js index 30989ff8deb710..ee46adf5de3c19 100644 --- a/src/ui/public/config/config.js +++ b/src/ui/public/config/config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import chrome from '../chrome'; import { isPlainObject } from 'lodash'; diff --git a/src/ui/public/config/index.js b/src/ui/public/config/index.js index c791e649224daf..54602df57d65cf 100644 --- a/src/ui/public/config/index.js +++ b/src/ui/public/config/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './config'; diff --git a/src/ui/public/courier/__tests__/request_queue.js b/src/ui/public/courier/__tests__/request_queue.js index 3ccda004d99921..8fe6976790c36e 100644 --- a/src/ui/public/courier/__tests__/request_queue.js +++ b/src/ui/public/courier/__tests__/request_queue.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; import sinon from 'sinon'; diff --git a/src/ui/public/courier/__tests__/saved_object.js b/src/ui/public/courier/__tests__/saved_object.js index ff703687dd5ad1..2c893b8e21128b 100644 --- a/src/ui/public/courier/__tests__/saved_object.js +++ b/src/ui/public/courier/__tests__/saved_object.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; import sinon from 'sinon'; @@ -169,7 +188,7 @@ describe('Saved Object', function () { const mockDocResponse = getMockedDocResponse('myId'); stubESResponse(mockDocResponse); return createInitializedSavedObject({ type: 'dashboard', id: 'myId' }).then(savedObject => { - sinon.stub(savedObjectsClientStub, 'create', function () { + sinon.stub(savedObjectsClientStub, 'create').callsFake(() => { return BluebirdPromise.resolve({ type: 'dashboard', id: 'newUniqueId' }); }); @@ -185,7 +204,7 @@ describe('Saved Object', function () { const mockDocResponse = getMockedDocResponse(originalId); stubESResponse(mockDocResponse); return createInitializedSavedObject({ type: 'dashboard', id: originalId }).then(savedObject => { - sinon.stub(savedObjectsClientStub, 'create', function () { + sinon.stub(savedObjectsClientStub, 'create').callsFake(() => { return BluebirdPromise.reject('simulated error'); }); savedObject.copyOnSave = true; @@ -203,7 +222,7 @@ describe('Saved Object', function () { stubESResponse(mockDocResponse); return createInitializedSavedObject({ type: 'dashboard', id: id }).then(savedObject => { - sinon.stub(savedObjectsClientStub, 'create', function () { + sinon.stub(savedObjectsClientStub, 'create').callsFake(() => { expect(savedObject.id).to.be(id); return BluebirdPromise.resolve(id); }); @@ -218,7 +237,7 @@ describe('Saved Object', function () { it('returns id from server on success', function () { return createInitializedSavedObject({ type: 'dashboard' }).then(savedObject => { const mockDocResponse = getMockedDocResponse('myId'); - sinon.stub(savedObjectsClientStub, 'create', function () { + sinon.stub(savedObjectsClientStub, 'create').callsFake(() => { return BluebirdPromise.resolve({ type: 'dashboard', id: 'myId', _version: 2 }); }); @@ -235,7 +254,7 @@ describe('Saved Object', function () { stubESResponse(getMockedDocResponse(id)); return createInitializedSavedObject({ type: 'dashboard', id: id }).then(savedObject => { - sinon.stub(savedObjectsClientStub, 'create', () => { + sinon.stub(savedObjectsClientStub, 'create').callsFake(() => { expect(savedObject.isSaving).to.be(true); return BluebirdPromise.resolve({ type: 'dashboard', id, version: 2 @@ -251,7 +270,7 @@ describe('Saved Object', function () { it('on failure', function () { stubESResponse(getMockedDocResponse('id')); return createInitializedSavedObject({ type: 'dashboard' }).then(savedObject => { - sinon.stub(savedObjectsClientStub, 'create', () => { + sinon.stub(savedObjectsClientStub, 'create').callsFake(() => { expect(savedObject.isSaving).to.be(true); return BluebirdPromise.reject(); }); diff --git a/src/ui/public/courier/_redirect_when_missing.js b/src/ui/public/courier/_redirect_when_missing.js index e5daa722321274..6d0577aa29339a 100644 --- a/src/ui/public/courier/_redirect_when_missing.js +++ b/src/ui/public/courier/_redirect_when_missing.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { SavedObjectNotFound } from '../errors'; export function RedirectWhenMissingProvider($location, kbnUrl, Notifier, Promise) { diff --git a/src/ui/public/courier/_request_queue.js b/src/ui/public/courier/_request_queue.js index f030fc6a3b68a0..12f75f68288fa8 100644 --- a/src/ui/public/courier/_request_queue.js +++ b/src/ui/public/courier/_request_queue.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Queue of pending requests, requests are removed as diff --git a/src/ui/public/courier/courier.js b/src/ui/public/courier/courier.js index 4dc8cb99d8be64..1b53c4214de2a7 100644 --- a/src/ui/public/courier/courier.js +++ b/src/ui/public/courier/courier.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import '../es'; diff --git a/src/ui/public/courier/data_source/__tests__/_migrate_filter.js b/src/ui/public/courier/data_source/__tests__/_migrate_filter.js index 2335f9d7a2db3e..c671e235772928 100644 --- a/src/ui/public/courier/data_source/__tests__/_migrate_filter.js +++ b/src/ui/public/courier/data_source/__tests__/_migrate_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import _ from 'lodash'; import { migrateFilter } from '../_migrate_filter'; diff --git a/src/ui/public/courier/data_source/__tests__/decorate_query.js b/src/ui/public/courier/data_source/__tests__/decorate_query.js index 00bb601726e7f6..29e85f1ee23c98 100644 --- a/src/ui/public/courier/data_source/__tests__/decorate_query.js +++ b/src/ui/public/courier/data_source/__tests__/decorate_query.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import chrome from '../../../chrome'; import { decorateQuery } from '../_decorate_query'; diff --git a/src/ui/public/courier/data_source/__tests__/normalize_sort_request.js b/src/ui/public/courier/data_source/__tests__/normalize_sort_request.js index 911e1ef2009996..7904fec79b84ef 100644 --- a/src/ui/public/courier/data_source/__tests__/normalize_sort_request.js +++ b/src/ui/public/courier/data_source/__tests__/normalize_sort_request.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import '../../../private'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/courier/data_source/__tests__/search_source.js b/src/ui/public/courier/data_source/__tests__/search_source.js index 3db1e4ca78c313..f9dbf938d143ec 100644 --- a/src/ui/public/courier/data_source/__tests__/search_source.js +++ b/src/ui/public/courier/data_source/__tests__/search_source.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; import sinon from 'sinon'; diff --git a/src/ui/public/courier/data_source/_decorate_query.js b/src/ui/public/courier/data_source/_decorate_query.js index 9237cd5a146c29..be80394aa646d7 100644 --- a/src/ui/public/courier/data_source/_decorate_query.js +++ b/src/ui/public/courier/data_source/_decorate_query.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import chrome from '../../chrome'; diff --git a/src/ui/public/courier/data_source/_migrate_filter.js b/src/ui/public/courier/data_source/_migrate_filter.js index 87ef3c27e962f9..63ad3270a8b2a8 100644 --- a/src/ui/public/courier/data_source/_migrate_filter.js +++ b/src/ui/public/courier/data_source/_migrate_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { getConvertedValueForField } from '../../filter_manager/lib/phrase'; diff --git a/src/ui/public/courier/data_source/_normalize_sort_request.js b/src/ui/public/courier/data_source/_normalize_sort_request.js index 9c104d68838d9c..aef37de2d11f55 100644 --- a/src/ui/public/courier/data_source/_normalize_sort_request.js +++ b/src/ui/public/courier/data_source/_normalize_sort_request.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function NormalizeSortRequestProvider(config) { diff --git a/src/ui/public/courier/data_source/_root_search_source.js b/src/ui/public/courier/data_source/_root_search_source.js index 0ce205cbfa7843..94943719c36137 100644 --- a/src/ui/public/courier/data_source/_root_search_source.js +++ b/src/ui/public/courier/data_source/_root_search_source.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { SearchSourceProvider } from './search_source'; export function RootSearchSourceProvider(Private, $rootScope, timefilter) { @@ -7,7 +26,15 @@ export function RootSearchSourceProvider(Private, $rootScope, timefilter) { globalSource.inherits(false); // this is the final source, it has no parents globalSource.filter(function (globalSource) { // dynamic time filter will be called in the _flatten phase of things - return timefilter.get(globalSource.get('index')); + const filter = timefilter.get(globalSource.get('index')); + // Attach a meta property to it, that we check inside visualizations + // to remove that timefilter again because we use our explicitly passed in one. + // This should be removed as soon as we got rid of inheritance in SearchSource + // across the boundary or visualization. + if (filter) { + filter.meta = { _globalTimefilter: true }; + } + return filter; }); let appSource; // set in setAppSource() diff --git a/src/ui/public/courier/data_source/build_query/__tests__/build_es_query.js b/src/ui/public/courier/data_source/build_query/__tests__/build_es_query.js index bbf0e74a545b76..e2317b1102d4ee 100644 --- a/src/ui/public/courier/data_source/build_query/__tests__/build_es_query.js +++ b/src/ui/public/courier/data_source/build_query/__tests__/build_es_query.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { BuildESQueryProvider } from '../build_es_query'; import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/courier/data_source/build_query/__tests__/from_filters.js b/src/ui/public/courier/data_source/build_query/__tests__/from_filters.js index 5887bddc80d705..b8d766b6fa960f 100644 --- a/src/ui/public/courier/data_source/build_query/__tests__/from_filters.js +++ b/src/ui/public/courier/data_source/build_query/__tests__/from_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { buildQueryFromFilters } from '../from_filters'; import ngMock from 'ng_mock'; import { expectDeepEqual } from '../../../../../../test_utils/expect_deep_equal.js'; diff --git a/src/ui/public/courier/data_source/build_query/__tests__/from_kuery.js b/src/ui/public/courier/data_source/build_query/__tests__/from_kuery.js index a6d314b792955e..d574af976ceea5 100644 --- a/src/ui/public/courier/data_source/build_query/__tests__/from_kuery.js +++ b/src/ui/public/courier/data_source/build_query/__tests__/from_kuery.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { buildQueryFromKuery } from '../from_kuery'; import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/courier/data_source/build_query/__tests__/from_lucene.js b/src/ui/public/courier/data_source/build_query/__tests__/from_lucene.js index ee6406bbea90cb..934971cda9ddcb 100644 --- a/src/ui/public/courier/data_source/build_query/__tests__/from_lucene.js +++ b/src/ui/public/courier/data_source/build_query/__tests__/from_lucene.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { buildQueryFromLucene } from '../from_lucene'; import { decorateQuery } from '../../_decorate_query.js'; import { expectDeepEqual } from '../../../../../../test_utils/expect_deep_equal.js'; diff --git a/src/ui/public/courier/data_source/build_query/__tests__/lucene_string_to_dsl.js b/src/ui/public/courier/data_source/build_query/__tests__/lucene_string_to_dsl.js index 7a2565d1d8b7c3..20467b99b51e85 100644 --- a/src/ui/public/courier/data_source/build_query/__tests__/lucene_string_to_dsl.js +++ b/src/ui/public/courier/data_source/build_query/__tests__/lucene_string_to_dsl.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { luceneStringToDsl } from '../lucene_string_to_dsl'; import { expectDeepEqual } from '../../../../../../test_utils/expect_deep_equal.js'; import expect from 'expect.js'; diff --git a/src/ui/public/courier/data_source/build_query/build_es_query.js b/src/ui/public/courier/data_source/build_query/build_es_query.js index 2b1733308ba125..55a354e26eca22 100644 --- a/src/ui/public/courier/data_source/build_query/build_es_query.js +++ b/src/ui/public/courier/data_source/build_query/build_es_query.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { groupBy, has } from 'lodash'; import { decorateQuery } from '../_decorate_query'; import { buildQueryFromKuery } from './from_kuery'; diff --git a/src/ui/public/courier/data_source/build_query/from_filters.js b/src/ui/public/courier/data_source/build_query/from_filters.js index 387319be2eb303..655ea3542757e9 100644 --- a/src/ui/public/courier/data_source/build_query/from_filters.js +++ b/src/ui/public/courier/data_source/build_query/from_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { migrateFilter } from '../_migrate_filter'; diff --git a/src/ui/public/courier/data_source/build_query/from_kuery.js b/src/ui/public/courier/data_source/build_query/from_kuery.js index ad428b23fea81b..d79be5f1f5a88a 100644 --- a/src/ui/public/courier/data_source/build_query/from_kuery.js +++ b/src/ui/public/courier/data_source/build_query/from_kuery.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fromLegacyKueryExpression, fromKueryExpression, toElasticsearchQuery, nodeTypes } from '../../../kuery'; import { documentationLinks } from '../../../documentation_links'; import { NoLeadingWildcardsError } from '../../../kuery/errors'; diff --git a/src/ui/public/courier/data_source/build_query/from_lucene.js b/src/ui/public/courier/data_source/build_query/from_lucene.js index c2ecb6142bf1c3..09bef032ef282b 100644 --- a/src/ui/public/courier/data_source/build_query/from_lucene.js +++ b/src/ui/public/courier/data_source/build_query/from_lucene.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { luceneStringToDsl } from './lucene_string_to_dsl'; diff --git a/src/ui/public/courier/data_source/build_query/index.js b/src/ui/public/courier/data_source/build_query/index.js index 20cf3a205a90bd..41b77cb74ed20b 100644 --- a/src/ui/public/courier/data_source/build_query/index.js +++ b/src/ui/public/courier/data_source/build_query/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { BuildESQueryProvider } from './build_es_query'; diff --git a/src/ui/public/courier/data_source/build_query/lucene_string_to_dsl.js b/src/ui/public/courier/data_source/build_query/lucene_string_to_dsl.js index 89711ab63926e3..36ff621e8a6948 100644 --- a/src/ui/public/courier/data_source/build_query/lucene_string_to_dsl.js +++ b/src/ui/public/courier/data_source/build_query/lucene_string_to_dsl.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function luceneStringToDsl(query) { diff --git a/src/ui/public/courier/data_source/search_source.js b/src/ui/public/courier/data_source/search_source.js index a4d6362f50307b..8de100592518c7 100644 --- a/src/ui/public/courier/data_source/search_source.js +++ b/src/ui/public/courier/data_source/search_source.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * @name SearchSource * diff --git a/src/ui/public/courier/fetch/__tests__/fetch_now.js b/src/ui/public/courier/fetch/__tests__/fetch_now.js index aff44b1f6f7376..c8a956e8604649 100644 --- a/src/ui/public/courier/fetch/__tests__/fetch_now.js +++ b/src/ui/public/courier/fetch/__tests__/fetch_now.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/courier/fetch/call_client.js b/src/ui/public/courier/fetch/call_client.js index 6613ef62181586..130bb57d9840d6 100644 --- a/src/ui/public/courier/fetch/call_client.js +++ b/src/ui/public/courier/fetch/call_client.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { ErrorAllowExplicitIndexProvider } from '../../error_allow_explicit_index'; diff --git a/src/ui/public/courier/fetch/call_response_handlers.js b/src/ui/public/courier/fetch/call_response_handlers.js index 80ef0d922f108b..94972fde9f2058 100644 --- a/src/ui/public/courier/fetch/call_response_handlers.js +++ b/src/ui/public/courier/fetch/call_response_handlers.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { RequestFailure, SearchTimeout, ShardFailure } from '../../errors'; import { RequestStatus } from './req_status'; diff --git a/src/ui/public/courier/fetch/continue_incomplete.js b/src/ui/public/courier/fetch/continue_incomplete.js index 8bbd1651d3656c..cca5fde71adfe8 100644 --- a/src/ui/public/courier/fetch/continue_incomplete.js +++ b/src/ui/public/courier/fetch/continue_incomplete.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { RequestStatus } from './req_status'; export function ContinueIncompleteProvider() { diff --git a/src/ui/public/courier/fetch/fetch_now.js b/src/ui/public/courier/fetch/fetch_now.js index 3a0e85de38080e..8a35949b5f49af 100644 --- a/src/ui/public/courier/fetch/fetch_now.js +++ b/src/ui/public/courier/fetch/fetch_now.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fatalError } from '../../notify'; import { CallClientProvider } from './call_client'; import { CallResponseHandlersProvider } from './call_response_handlers'; diff --git a/src/ui/public/courier/fetch/fetch_soon.js b/src/ui/public/courier/fetch/fetch_soon.js index c60f0f8508ddc1..f7d0d444d76c26 100644 --- a/src/ui/public/courier/fetch/fetch_soon.js +++ b/src/ui/public/courier/fetch/fetch_soon.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { requestQueue } from '../_request_queue'; import { FetchNowProvider } from './fetch_now'; diff --git a/src/ui/public/courier/fetch/index.js b/src/ui/public/courier/fetch/index.js index 9630f2b26651ae..91c3fe67990e30 100644 --- a/src/ui/public/courier/fetch/index.js +++ b/src/ui/public/courier/fetch/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { FetchSoonProvider } from './fetch_soon'; diff --git a/src/ui/public/courier/fetch/is_request.js b/src/ui/public/courier/fetch/is_request.js index 9a9966f47c2983..73c54d6f4bca1d 100644 --- a/src/ui/public/courier/fetch/is_request.js +++ b/src/ui/public/courier/fetch/is_request.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { SearchRequestProvider } from './request'; export function IsRequestProvider(Private) { diff --git a/src/ui/public/courier/fetch/merge_duplicate_requests.js b/src/ui/public/courier/fetch/merge_duplicate_requests.js index 8535827242a4c4..eb4cbc29bcb099 100644 --- a/src/ui/public/courier/fetch/merge_duplicate_requests.js +++ b/src/ui/public/courier/fetch/merge_duplicate_requests.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { IsRequestProvider } from './is_request'; import { RequestStatus } from './req_status'; diff --git a/src/ui/public/courier/fetch/notifier.js b/src/ui/public/courier/fetch/notifier.js index 58dfdcfe61f741..57cbb18337a7b6 100644 --- a/src/ui/public/courier/fetch/notifier.js +++ b/src/ui/public/courier/fetch/notifier.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Notifier } from '../../notify'; export const location = 'Courier fetch'; diff --git a/src/ui/public/courier/fetch/req_status.js b/src/ui/public/courier/fetch/req_status.js index efec1c26e2a3d4..a5ef380b86c6c2 100644 --- a/src/ui/public/courier/fetch/req_status.js +++ b/src/ui/public/courier/fetch/req_status.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const RequestStatus = { ABORTED: 'aborted', DUPLICATE: 'duplicate', diff --git a/src/ui/public/courier/fetch/request/__tests__/request_fetch_params_to_body_provider.js b/src/ui/public/courier/fetch/request/__tests__/request_fetch_params_to_body_provider.js index b276546ed20fad..0aab1d7c4d4ba8 100644 --- a/src/ui/public/courier/fetch/request/__tests__/request_fetch_params_to_body_provider.js +++ b/src/ui/public/courier/fetch/request/__tests__/request_fetch_params_to_body_provider.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/courier/fetch/request/__tests__/search_request.js b/src/ui/public/courier/fetch/request/__tests__/search_request.js index 6a1b6e53f4e48d..3d18b494e64e86 100644 --- a/src/ui/public/courier/fetch/request/__tests__/search_request.js +++ b/src/ui/public/courier/fetch/request/__tests__/search_request.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import sinon from 'sinon'; import expect from 'expect.js'; diff --git a/src/ui/public/courier/fetch/request/__tests__/segmented.js b/src/ui/public/courier/fetch/request/__tests__/segmented.js index cec4f55b8b5858..7896ab1165772a 100644 --- a/src/ui/public/courier/fetch/request/__tests__/segmented.js +++ b/src/ui/public/courier/fetch/request/__tests__/segmented.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; import ngMock from 'ng_mock'; @@ -18,7 +37,7 @@ describe('SegmentedRequestProvider', () => { SegmentedReq = Private(SegmentedRequestProvider); const SearchRequest = Private(SearchRequestProvider); - abstractReqStart = sinon.stub(SearchRequest.prototype, 'start', () => { + abstractReqStart = sinon.stub(SearchRequest.prototype, 'start').callsFake(() => { const promise = Promise.resolve(); sinon.spy(promise, 'then'); return promise; diff --git a/src/ui/public/courier/fetch/request/__tests__/segmented_create_queue.js b/src/ui/public/courier/fetch/request/__tests__/segmented_create_queue.js index edf7e725dc53bb..5e4e678de308f0 100644 --- a/src/ui/public/courier/fetch/request/__tests__/segmented_create_queue.js +++ b/src/ui/public/courier/fetch/request/__tests__/segmented_create_queue.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/courier/fetch/request/__tests__/segmented_index_selection.js b/src/ui/public/courier/fetch/request/__tests__/segmented_index_selection.js index 25b8a8426ad469..539722a88db509 100644 --- a/src/ui/public/courier/fetch/request/__tests__/segmented_index_selection.js +++ b/src/ui/public/courier/fetch/request/__tests__/segmented_index_selection.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; import { times } from 'lodash'; diff --git a/src/ui/public/courier/fetch/request/__tests__/segmented_size_picking.js b/src/ui/public/courier/fetch/request/__tests__/segmented_size_picking.js index 69ea3bba925c03..0ddb8543ef9dd7 100644 --- a/src/ui/public/courier/fetch/request/__tests__/segmented_size_picking.js +++ b/src/ui/public/courier/fetch/request/__tests__/segmented_size_picking.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/courier/fetch/request/index.js b/src/ui/public/courier/fetch/request/index.js index c73cad3e4bc2a4..6647d0e5b2e102 100644 --- a/src/ui/public/courier/fetch/request/index.js +++ b/src/ui/public/courier/fetch/request/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { SearchRequestProvider } from './search_request'; diff --git a/src/ui/public/courier/fetch/request/request_fetch_params_to_body.js b/src/ui/public/courier/fetch/request/request_fetch_params_to_body.js index 97e41473155099..f8daefe1f3e462 100644 --- a/src/ui/public/courier/fetch/request/request_fetch_params_to_body.js +++ b/src/ui/public/courier/fetch/request/request_fetch_params_to_body.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { toJson } from '../../../../../core_plugins/kibana/common/utils/aggressive_parse'; diff --git a/src/ui/public/courier/fetch/request/request_fetch_params_to_body.test.js b/src/ui/public/courier/fetch/request/request_fetch_params_to_body.test.js index e289ed82c9131f..d7c6ea8b9c2ef3 100644 --- a/src/ui/public/courier/fetch/request/request_fetch_params_to_body.test.js +++ b/src/ui/public/courier/fetch/request/request_fetch_params_to_body.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { requestFetchParamsToBody } from './request_fetch_params_to_body'; import _ from 'lodash'; diff --git a/src/ui/public/courier/fetch/request/request_fetch_params_to_body_provider.js b/src/ui/public/courier/fetch/request/request_fetch_params_to_body_provider.js index 82e4e940499373..22f6bf534573d7 100644 --- a/src/ui/public/courier/fetch/request/request_fetch_params_to_body_provider.js +++ b/src/ui/public/courier/fetch/request/request_fetch_params_to_body_provider.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { requestFetchParamsToBody } from './request_fetch_params_to_body'; export function RequestFetchParamsToBodyProvider(Promise, timefilter, kbnIndex, sessionId, config, esShardTimeout) { diff --git a/src/ui/public/courier/fetch/request/search_request.js b/src/ui/public/courier/fetch/request/search_request.js index 425b588a8134a9..9fab732cd8fa7d 100644 --- a/src/ui/public/courier/fetch/request/search_request.js +++ b/src/ui/public/courier/fetch/request/search_request.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import moment from 'moment'; diff --git a/src/ui/public/courier/fetch/request/segmented.js b/src/ui/public/courier/fetch/request/segmented.js index e398e5830bcf08..125737b4ddab6d 100644 --- a/src/ui/public/courier/fetch/request/segmented.js +++ b/src/ui/public/courier/fetch/request/segmented.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { Notifier } from '../../../notify'; import { SearchRequestProvider } from './search_request'; @@ -88,7 +107,7 @@ export function SegmentedRequestProvider(Private, timefilter, config) { const indexCount = Math.max(1, Math.floor(this._queue.length / remainingSegments)); const indices = this._active = this._queue.splice(0, indexCount); - params.index = _.pluck(indices, 'index'); + params.index = indices.map(({ index }) => index).join(','); if (_.isNumber(this._desiredSize)) { params.body.size = this._pickSizeForIndices(indices); diff --git a/src/ui/public/courier/fetch/request/segmented_handle.js b/src/ui/public/courier/fetch/request/segmented_handle.js index cc6721700f01d1..ed443fc94e616d 100644 --- a/src/ui/public/courier/fetch/request/segmented_handle.js +++ b/src/ui/public/courier/fetch/request/segmented_handle.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { EventsProvider } from '../../../events'; export function SegmentedHandleProvider(Private) { diff --git a/src/ui/public/courier/index.js b/src/ui/public/courier/index.js index 96df31b949bf5e..9efb2954c99b24 100644 --- a/src/ui/public/courier/index.js +++ b/src/ui/public/courier/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './courier'; diff --git a/src/ui/public/courier/looper/_looper.js b/src/ui/public/courier/looper/_looper.js index 3025adfb73e4a7..295c98f9d47e7a 100644 --- a/src/ui/public/courier/looper/_looper.js +++ b/src/ui/public/courier/looper/_looper.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import '../../promises'; diff --git a/src/ui/public/courier/looper/search.js b/src/ui/public/courier/looper/search.js index c75a2d44074ec1..8bdf79400e2e77 100644 --- a/src/ui/public/courier/looper/search.js +++ b/src/ui/public/courier/looper/search.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { FetchSoonProvider } from '../fetch'; import { requestQueue } from '../_request_queue'; import { LooperProvider } from './_looper'; diff --git a/src/ui/public/courier/saved_object/index.js b/src/ui/public/courier/saved_object/index.js index ee774221824d3b..b5b0e56bf57a20 100644 --- a/src/ui/public/courier/saved_object/index.js +++ b/src/ui/public/courier/saved_object/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { SavedObjectProvider } from './saved_object'; diff --git a/src/ui/public/courier/saved_object/saved_object.js b/src/ui/public/courier/saved_object/saved_object.js index 64d49c945b54bc..04533d63fb8114 100644 --- a/src/ui/public/courier/saved_object/saved_object.js +++ b/src/ui/public/courier/saved_object/saved_object.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * @name SavedObject * @@ -283,12 +302,21 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm }); }; - /** - * Returns a promise that resolves to true if either the title is unique, or if the user confirmed they - * wished to save the duplicate title. Promise is rejected if the user rejects the confirmation. - */ - const warnIfDuplicateTitle = () => { - // Don't warn if the user isn't updating the title, otherwise that would become very annoying to have + const displayDuplicateTitleConfirmModal = () => { + const confirmMessage = + `A ${this.getDisplayName()} with the title '${this.title}' already exists. Would you like to save anyway?`; + + return confirmModalPromise(confirmMessage, { confirmButtonText: `Save ${this.getDisplayName()}` }) + .catch(() => Promise.reject(new Error(SAVE_DUPLICATE_REJECTED))); + }; + + const checkForDuplicateTitle = (isTitleDuplicateConfirmed, onTitleDuplicate) => { + // Don't check for duplicates if user has already confirmed save with duplicate title + if (isTitleDuplicateConfirmed) { + return Promise.resolve(); + } + + // Don't check if the user isn't updating the title, otherwise that would become very annoying to have // to confirm the save every time, except when copyOnSave is true, then we do want to check. if (this.title === this.lastSavedTitle && !this.copyOnSave) { return Promise.resolve(); @@ -299,11 +327,14 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm if (!duplicate) return true; if (duplicate.id === this.id) return true; - const confirmMessage = - `A ${this.getDisplayName()} with the title '${this.title}' already exists. Would you like to save anyway?`; + if (onTitleDuplicate) { + onTitleDuplicate(); + return Promise.reject(new Error(SAVE_DUPLICATE_REJECTED)); + } - return confirmModalPromise(confirmMessage, { confirmButtonText: `Save ${this.getDisplayName()}` }) - .catch(() => Promise.reject(new Error(SAVE_DUPLICATE_REJECTED))); + // TODO: make onTitleDuplicate a required prop and remove UI components from this class + // Need to leave here until all users pass onTitleDuplicate. + return displayDuplicateTitleConfirmModal(); }); }; @@ -313,10 +344,13 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm * @param {object} [options={}] * @property {boolean} [options.confirmOverwrite=false] - If true, attempts to create the source so it * can confirm an overwrite if a document with the id already exists. + * @property {boolean} [options.isTitleDuplicateConfirmed=false] - If true, save allowed with duplicate title + * @property {func} [options.onTitleDuplicate] - function called if duplicate title exists. + * When not provided, confirm modal will be displayed asking user to confirm or cancel save. * @return {Promise} * @resolved {String} - The id of the doc */ - this.save = ({ confirmOverwrite } = {}) => { + this.save = ({ confirmOverwrite = false, isTitleDuplicateConfirmed = false, onTitleDuplicate } = {}) => { // Save the original id in case the save fails. const originalId = this.id; // Read https://github.com/elastic/kibana/issues/9056 and @@ -333,7 +367,7 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm this.isSaving = true; - return warnIfDuplicateTitle() + return checkForDuplicateTitle(isTitleDuplicateConfirmed, onTitleDuplicate) .then(() => { if (confirmOverwrite) { return createSource(source); diff --git a/src/ui/public/courier/saved_object/saved_object_loader.js b/src/ui/public/courier/saved_object/saved_object_loader.js index cd662695238995..7a6f2b27db9316 100644 --- a/src/ui/public/courier/saved_object/saved_object_loader.js +++ b/src/ui/public/courier/saved_object/saved_object_loader.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Scanner } from '../../utils/scanner'; import { StringUtils } from '../../utils/string_utils'; import { SavedObjectsClient } from '../../saved_objects'; @@ -94,14 +113,15 @@ export class SavedObjectLoader { * @param size * @returns {Promise} */ - findAll(search = '', size = 100) { + findAll(search = '', size = 100, fields) { return this.savedObjectsClient.find( { type: this.lowercaseType, search: search ? `${search}*` : undefined, perPage: size, page: 1, - searchFields: ['title^3', 'description'] + searchFields: ['title^3', 'description'], + fields, }).then((resp) => { return { total: resp.total, diff --git a/src/ui/public/courier/saved_object/ui/saved_object_save_as_checkbox.js b/src/ui/public/courier/saved_object/ui/saved_object_save_as_checkbox.js index 27c8c5287ae7fc..f3f089653c329a 100644 --- a/src/ui/public/courier/saved_object/ui/saved_object_save_as_checkbox.js +++ b/src/ui/public/courier/saved_object/ui/saved_object_save_as_checkbox.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../../../modules'; import saveObjectSaveAsCheckboxTemplate from './saved_object_save_as_checkbox.html'; diff --git a/src/ui/public/crypto/index.js b/src/ui/public/crypto/index.js index 9951cf805cb85b..eda07d53147e20 100644 --- a/src/ui/public/crypto/index.js +++ b/src/ui/public/crypto/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { Sha256 } from './sha256'; diff --git a/src/ui/public/crypto/sha256.js b/src/ui/public/crypto/sha256.js index 1c6de18b1dfab5..c97d9046f9555b 100644 --- a/src/ui/public/crypto/sha256.js +++ b/src/ui/public/crypto/sha256.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // ported from https://github.com/spalger/sha.js/blob/6557630d508873e262e94bff70c50bdd797c1df7/sha256.js // and https://github.com/spalger/sha.js/blob/6557630d508873e262e94bff70c50bdd797c1df7/hash.js diff --git a/src/ui/public/dashboard_panel_actions/dashboard_context_menu_panel.js b/src/ui/public/dashboard_panel_actions/dashboard_context_menu_panel.js new file mode 100644 index 00000000000000..03537d846f3b9e --- /dev/null +++ b/src/ui/public/dashboard_panel_actions/dashboard_context_menu_panel.js @@ -0,0 +1,43 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export class DashboardContextMenuPanel { + /** + * @param {string} id + * @param {string} title + * @param {function} getContent + */ + constructor({ id, title, getContent }) { + this.id = id; + this.title = title; + + if (getContent) { + this.getContent = getContent; + } + } + + /** + * Optional, could be composed of actions instead of content. + * @param {Embeddable} embeddable + * @param {ContainerState} containerState + */ + getContent(/*{ embeddable, containerState }*/) { + return null; + } +} diff --git a/src/ui/public/dashboard_panel_actions/dashboard_panel_action.js b/src/ui/public/dashboard_panel_actions/dashboard_panel_action.js new file mode 100644 index 00000000000000..15f3178d1eda12 --- /dev/null +++ b/src/ui/public/dashboard_panel_actions/dashboard_panel_action.js @@ -0,0 +1,86 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export class DashboardPanelAction { + /** + * + * @param {string} id + * @param {string} displayName + * @param {function} onClick + * @param {DashboardContextMenuPanel} childContextMenuPanel - optional child panel to open when clicked. + * @param {function} isDisabled - optionally set a custom disabled function + * @param {function} isVisible - optionally set a custom isVisible function + * @param {string} parentPanelId - set if this action belongs on a nested child panel + * @param {Element} icon + */ + constructor( + { + id, + displayName, + onClick, + childContextMenuPanel, + isDisabled, + isVisible, + parentPanelId, + icon, + } = {}) { + this.id = id; + this.icon = icon; + this.displayName = displayName; + this.childContextMenuPanel = childContextMenuPanel; + this.parentPanelId = parentPanelId; + + if (onClick) { + this.onClick = onClick; + } + + if (isDisabled) { + this.isDisabled = isDisabled; + } + + if (isVisible) { + this.isVisible = isVisible; + } + } + + /** + * @param {Embeddable} embeddable + * @param ContainerState} containerState + */ + onClick(/*{ embeddable, containerState }*/) {} + + /** + * Defaults to always visible. + * @param {Embeddable} embeddable + * @param ContainerState} containerState + * @return {boolean} + */ + isVisible(/*{ embeddable, containerState }*/) { + return true; + } + + /** + * Defaults to always enabled. + * @param {Embeddable} embeddable + * @param {ContainerState} containerState + */ + isDisabled(/*{ embeddable, containerState }*/) { + return false; + } +} diff --git a/src/ui/public/dashboard_panel_actions/dashboard_panel_actions_registry.js b/src/ui/public/dashboard_panel_actions/dashboard_panel_actions_registry.js new file mode 100644 index 00000000000000..4d3c017b3cf055 --- /dev/null +++ b/src/ui/public/dashboard_panel_actions/dashboard_panel_actions_registry.js @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { uiRegistry } from 'ui/registry/_registry'; + +export const DashboardPanelActionsRegistryProvider = uiRegistry({ + name: 'dashboardPanelActions', + index: ['name'], +}); diff --git a/src/ui/public/dashboard_panel_actions/index.js b/src/ui/public/dashboard_panel_actions/index.js new file mode 100644 index 00000000000000..759ece6ec56a68 --- /dev/null +++ b/src/ui/public/dashboard_panel_actions/index.js @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { DashboardPanelAction } from './dashboard_panel_action'; +export { DashboardPanelActionsRegistryProvider } from './dashboard_panel_actions_registry'; +export { DashboardContextMenuPanel } from './dashboard_context_menu_panel'; diff --git a/src/ui/public/debounce/__tests__/debounce.js b/src/ui/public/debounce/__tests__/debounce.js index 939ba6b2eda064..5aa4233613ce16 100644 --- a/src/ui/public/debounce/__tests__/debounce.js +++ b/src/ui/public/debounce/__tests__/debounce.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; @@ -35,7 +54,7 @@ describe('debounce service', function () { }); describe('delayed execution', function () { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); beforeEach(() => sandbox.useFakeTimers()); afterEach(() => sandbox.restore()); @@ -49,7 +68,7 @@ describe('debounce service', function () { $timeout.flush(); sinon.assert.calledOnce(spy); - spy.reset(); + spy.resetHistory(); bouncerFromProvider(); sinon.assert.notCalled(spy); @@ -66,7 +85,7 @@ describe('debounce service', function () { $timeout.flush(); sinon.assert.calledTwice(spy); - spy.reset(); + spy.resetHistory(); bouncerFromProvider(); sinon.assert.calledOnce(spy); @@ -83,7 +102,7 @@ describe('debounce service', function () { $timeout.flush(); sinon.assert.calledOnce(spy); - spy.reset(); + spy.resetHistory(); bouncerFromProvider(); sinon.assert.calledOnce(spy); @@ -105,8 +124,8 @@ describe('debounce service', function () { sinon.assert.calledOnce(spy); sinon.assert.calledOnce(cancelSpy); - spy.reset(); - cancelSpy.reset(); + spy.resetHistory(); + cancelSpy.resetHistory(); bouncerFromProvider(); sandbox.clock.tick(1); @@ -131,7 +150,7 @@ describe('debounce service', function () { // throws if pending timeouts $timeout.verifyNoPendingTasks(); - cancelSpy.reset(); + cancelSpy.resetHistory(); bouncerFromProvider(); bouncerFromProvider.cancel(); diff --git a/src/ui/public/debounce/debounce.js b/src/ui/public/debounce/debounce.js index 3f076d8f8fa740..0791001c32e3a9 100644 --- a/src/ui/public/debounce/debounce.js +++ b/src/ui/public/debounce/debounce.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { uiModules } from '../modules'; // Debounce service, angularized version of lodash debounce diff --git a/src/ui/public/debounce/index.js b/src/ui/public/debounce/index.js index b267626b201d3f..35b83392636263 100644 --- a/src/ui/public/debounce/index.js +++ b/src/ui/public/debounce/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './debounce'; export { DebounceProvider } from './debounce'; diff --git a/src/ui/public/directives/__tests__/auto_select_if_only_one.js b/src/ui/public/directives/__tests__/auto_select_if_only_one.js index 6f5240e5743d1f..0830041207e6cf 100644 --- a/src/ui/public/directives/__tests__/auto_select_if_only_one.js +++ b/src/ui/public/directives/__tests__/auto_select_if_only_one.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/directives/__tests__/confirm-click.js b/src/ui/public/directives/__tests__/confirm-click.js index 12dc2a165d9c1f..08bce6aea47a6c 100644 --- a/src/ui/public/directives/__tests__/confirm-click.js +++ b/src/ui/public/directives/__tests__/confirm-click.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/directives/__tests__/css_truncate.js b/src/ui/public/directives/__tests__/css_truncate.js index e78f2f63d89fbf..3c851a7df68427 100644 --- a/src/ui/public/directives/__tests__/css_truncate.js +++ b/src/ui/public/directives/__tests__/css_truncate.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/directives/__tests__/fixed_scroll.js b/src/ui/public/directives/__tests__/fixed_scroll.js index 068e92d1a4aec3..cec917cf4d1f7a 100644 --- a/src/ui/public/directives/__tests__/fixed_scroll.js +++ b/src/ui/public/directives/__tests__/fixed_scroll.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; @@ -6,7 +25,7 @@ import $ from 'jquery'; import sinon from 'sinon'; describe('FixedScroll directive', function () { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); let compile; let flushPendingTasks; @@ -156,7 +175,7 @@ describe('FixedScroll directive', function () { $from.scroll(); expect(spy.callCount).to.be(2); - spy.reset(); + spy.resetHistory(); $to.scroll(); expect(spy.callCount).to.be(0); }); diff --git a/src/ui/public/directives/__tests__/inequality.js b/src/ui/public/directives/__tests__/inequality.js index c777c74b2db94b..a513520e49791c 100644 --- a/src/ui/public/directives/__tests__/inequality.js +++ b/src/ui/public/directives/__tests__/inequality.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import '../inequality'; diff --git a/src/ui/public/directives/__tests__/input_focus.js b/src/ui/public/directives/__tests__/input_focus.js index 3b11a79bf1e876..9b1bbe25c844c3 100644 --- a/src/ui/public/directives/__tests__/input_focus.js +++ b/src/ui/public/directives/__tests__/input_focus.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import $ from 'jquery'; diff --git a/src/ui/public/directives/__tests__/input_number.js b/src/ui/public/directives/__tests__/input_number.js index ca2abbf85b4d89..a60b38839494ee 100644 --- a/src/ui/public/directives/__tests__/input_number.js +++ b/src/ui/public/directives/__tests__/input_number.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import '../input_number'; diff --git a/src/ui/public/directives/__tests__/json_input.js b/src/ui/public/directives/__tests__/json_input.js index 061dae7f088cae..43ecea162f1665 100644 --- a/src/ui/public/directives/__tests__/json_input.js +++ b/src/ui/public/directives/__tests__/json_input.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import '../json_input'; diff --git a/src/ui/public/directives/__tests__/paginated_selectable_list.js b/src/ui/public/directives/__tests__/paginated_selectable_list.js index 30c5f906a5e373..5246cc3568fd8c 100644 --- a/src/ui/public/directives/__tests__/paginated_selectable_list.js +++ b/src/ui/public/directives/__tests__/paginated_selectable_list.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/directives/__tests__/parse_query.js b/src/ui/public/directives/__tests__/parse_query.js index 4ae124eabc7156..b3c24cc9deb8b1 100644 --- a/src/ui/public/directives/__tests__/parse_query.js +++ b/src/ui/public/directives/__tests__/parse_query.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/directives/__tests__/timepicker.js b/src/ui/public/directives/__tests__/timepicker.js index 7b4f1bd57ea697..64899901532f9a 100644 --- a/src/ui/public/directives/__tests__/timepicker.js +++ b/src/ui/public/directives/__tests__/timepicker.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import moment from 'moment'; import expect from 'expect.js'; @@ -70,7 +89,7 @@ const init = function () { describe('timepicker directive', function () { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); beforeEach(function () { // Stub out the clock so 'now' doesn't move diff --git a/src/ui/public/directives/__tests__/truncate.js b/src/ui/public/directives/__tests__/truncate.js index a3a6df574658ff..864db638056912 100644 --- a/src/ui/public/directives/__tests__/truncate.js +++ b/src/ui/public/directives/__tests__/truncate.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/directives/__tests__/validate_cidr_mask.js b/src/ui/public/directives/__tests__/validate_cidr_mask.js index 434b12b70d901f..b1a6724f18ee69 100644 --- a/src/ui/public/directives/__tests__/validate_cidr_mask.js +++ b/src/ui/public/directives/__tests__/validate_cidr_mask.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import '../validate_cidr_mask'; diff --git a/src/ui/public/directives/__tests__/validate_date_math.js b/src/ui/public/directives/__tests__/validate_date_math.js index fccc8ced9bdd7e..e7689984c969b1 100644 --- a/src/ui/public/directives/__tests__/validate_date_math.js +++ b/src/ui/public/directives/__tests__/validate_date_math.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import '../validate_date_math'; diff --git a/src/ui/public/directives/__tests__/validate_index_pattern.js b/src/ui/public/directives/__tests__/validate_index_pattern.js index 3993bee67a7829..ae90248adb098a 100644 --- a/src/ui/public/directives/__tests__/validate_index_pattern.js +++ b/src/ui/public/directives/__tests__/validate_index_pattern.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import '../validate_index_pattern'; diff --git a/src/ui/public/directives/__tests__/validate_ip.js b/src/ui/public/directives/__tests__/validate_ip.js index bea95871d04a8c..f2181ea08edfb1 100644 --- a/src/ui/public/directives/__tests__/validate_ip.js +++ b/src/ui/public/directives/__tests__/validate_ip.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import '../validate_ip'; diff --git a/src/ui/public/directives/__tests__/validate_json.js b/src/ui/public/directives/__tests__/validate_json.js index f8a4fda3994b83..b59ee7bccf7ec4 100644 --- a/src/ui/public/directives/__tests__/validate_json.js +++ b/src/ui/public/directives/__tests__/validate_json.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/directives/auto_select_if_only_one.js b/src/ui/public/directives/auto_select_if_only_one.js index 150ef3f0e858d5..1b27132eb2b594 100644 --- a/src/ui/public/directives/auto_select_if_only_one.js +++ b/src/ui/public/directives/auto_select_if_only_one.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/click_focus.js b/src/ui/public/directives/click_focus.js index f969f3032a1c97..deccbfd1b3e95b 100644 --- a/src/ui/public/directives/click_focus.js +++ b/src/ui/public/directives/click_focus.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import $ from 'jquery'; import { uiModules } from '../modules'; diff --git a/src/ui/public/directives/confirm_click.js b/src/ui/public/directives/confirm_click.js index 541f6a9b0e72ee..cbee20e01d9693 100644 --- a/src/ui/public/directives/confirm_click.js +++ b/src/ui/public/directives/confirm_click.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; uiModules .get('kibana') diff --git a/src/ui/public/directives/css_truncate.js b/src/ui/public/directives/css_truncate.js index d34b2c10436517..7105563e0ce5f2 100644 --- a/src/ui/public/directives/css_truncate.js +++ b/src/ui/public/directives/css_truncate.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/documentation_href.js b/src/ui/public/directives/documentation_href.js index b84fb24e23f81e..70473746334fbf 100644 --- a/src/ui/public/directives/documentation_href.js +++ b/src/ui/public/directives/documentation_href.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { getDocLink } from '../documentation_links'; import { uiModules } from '../modules'; diff --git a/src/ui/public/directives/field_name.js b/src/ui/public/directives/field_name.js index 5c76fff1753c13..233900e5c963b2 100644 --- a/src/ui/public/directives/field_name.js +++ b/src/ui/public/directives/field_name.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import '../filters/short_dots'; import booleanFieldNameIcon from './field_name_icons/boolean_field_name_icon.html'; diff --git a/src/ui/public/directives/file_upload.js b/src/ui/public/directives/file_upload.js index 11091f218e0df6..b0ce52bd2a314a 100644 --- a/src/ui/public/directives/file_upload.js +++ b/src/ui/public/directives/file_upload.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import $ from 'jquery'; import { uiModules } from '../modules'; diff --git a/src/ui/public/directives/focus_on.js b/src/ui/public/directives/focus_on.js index ec8a075fdbb518..9b53c4fd7c780f 100644 --- a/src/ui/public/directives/focus_on.js +++ b/src/ui/public/directives/focus_on.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/inequality.js b/src/ui/public/directives/inequality.js index abcbf557438ba5..d3c80d1ff2e969 100644 --- a/src/ui/public/directives/inequality.js +++ b/src/ui/public/directives/inequality.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; function makeDirectiveDef(id, compare) { diff --git a/src/ui/public/directives/infinite_scroll.js b/src/ui/public/directives/infinite_scroll.js index ee82275c892589..6f8132e1ee7d97 100644 --- a/src/ui/public/directives/infinite_scroll.js +++ b/src/ui/public/directives/infinite_scroll.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/input_base64.js b/src/ui/public/directives/input_base64.js index fe2b7014e89e7b..d6767cb7d80ca0 100644 --- a/src/ui/public/directives/input_base64.js +++ b/src/ui/public/directives/input_base64.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; import { Observable } from 'rxjs/Rx'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/input_datetime.js b/src/ui/public/directives/input_datetime.js index 37ff175eb30d01..acc62d309aac73 100644 --- a/src/ui/public/directives/input_datetime.js +++ b/src/ui/public/directives/input_datetime.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import moment from 'moment'; import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/input_focus.js b/src/ui/public/directives/input_focus.js index e0da9ab100c1ac..f1ed2a82045a01 100644 --- a/src/ui/public/directives/input_focus.js +++ b/src/ui/public/directives/input_focus.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/input_number.js b/src/ui/public/directives/input_number.js index 37d40fcae8ca65..44bef86157882c 100644 --- a/src/ui/public/directives/input_number.js +++ b/src/ui/public/directives/input_number.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/json_input.js b/src/ui/public/directives/json_input.js index 552c39dfa9da3c..4ba2df2facd4f4 100644 --- a/src/ui/public/directives/json_input.js +++ b/src/ui/public/directives/json_input.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import angular from 'angular'; import { uiModules } from '../modules'; diff --git a/src/ui/public/directives/kbn_href.js b/src/ui/public/directives/kbn_href.js index 868b654f46991c..9fe513c78b2d52 100644 --- a/src/ui/public/directives/kbn_href.js +++ b/src/ui/public/directives/kbn_href.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; import { words, kebabCase } from 'lodash'; diff --git a/src/ui/public/directives/kbn_src.js b/src/ui/public/directives/kbn_src.js index 208ecf1144ac8c..1bf19266cbcec1 100644 --- a/src/ui/public/directives/kbn_src.js +++ b/src/ui/public/directives/kbn_src.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { kbnUrlDirective } from './kbn_href'; kbnUrlDirective('kbnSrc'); diff --git a/src/ui/public/directives/match_pairs.js b/src/ui/public/directives/match_pairs.js index b175824712987d..a68469340edb9c 100644 --- a/src/ui/public/directives/match_pairs.js +++ b/src/ui/public/directives/match_pairs.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/paginate.js b/src/ui/public/directives/paginate.js index 065291721a3ad6..4302a48f0f8e78 100644 --- a/src/ui/public/directives/paginate.js +++ b/src/ui/public/directives/paginate.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { uiModules } from '../modules'; import paginateControlsTemplate from '../partials/paginate_controls.html'; diff --git a/src/ui/public/directives/paginated_selectable_list.js b/src/ui/public/directives/paginated_selectable_list.js index d1c2880e11ffaa..e71c6dc67e286d 100644 --- a/src/ui/public/directives/paginated_selectable_list.js +++ b/src/ui/public/directives/paginated_selectable_list.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { uiModules } from '../modules'; import paginatedSelectableListTemplate from '../partials/paginated_selectable_list.html'; diff --git a/src/ui/public/directives/pretty_duration.js b/src/ui/public/directives/pretty_duration.js index fe984b41780a66..01cbb645b1604e 100644 --- a/src/ui/public/directives/pretty_duration.js +++ b/src/ui/public/directives/pretty_duration.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; import { prettyDuration } from '../timepicker/pretty_duration'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/rows.js b/src/ui/public/directives/rows.js index e1eb885abac2a7..97e7a890ce51f1 100644 --- a/src/ui/public/directives/rows.js +++ b/src/ui/public/directives/rows.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import _ from 'lodash'; import AggConfigResult from '../vis/agg_config_result'; diff --git a/src/ui/public/directives/saved_object_finder.js b/src/ui/public/directives/saved_object_finder.js index 07d7435a2ed33f..ad9905047f0b62 100644 --- a/src/ui/public/directives/saved_object_finder.js +++ b/src/ui/public/directives/saved_object_finder.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import rison from 'rison-node'; import { keyMap } from '../utils/key_map'; diff --git a/src/ui/public/directives/scroll_bottom.js b/src/ui/public/directives/scroll_bottom.js index 3b998da586019e..1648cc37aee637 100644 --- a/src/ui/public/directives/scroll_bottom.js +++ b/src/ui/public/directives/scroll_bottom.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/string_to_number.js b/src/ui/public/directives/string_to_number.js index 99bcb060b973f2..40ffbe69d499a9 100644 --- a/src/ui/public/directives/string_to_number.js +++ b/src/ui/public/directives/string_to_number.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/truncated.js b/src/ui/public/directives/truncated.js index ca17bb79e6ae5c..60bd77136c8fef 100644 --- a/src/ui/public/directives/truncated.js +++ b/src/ui/public/directives/truncated.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import truncText from 'trunc-text'; import truncHTML from 'trunc-html'; import { uiModules } from '../modules'; diff --git a/src/ui/public/directives/ui_select_focus_on.js b/src/ui/public/directives/ui_select_focus_on.js index 540c5e65c48ee4..445035d6c036bf 100644 --- a/src/ui/public/directives/ui_select_focus_on.js +++ b/src/ui/public/directives/ui_select_focus_on.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/validate_agg.js b/src/ui/public/directives/validate_agg.js index 2295a040aebcf1..3abfba334d8c3f 100644 --- a/src/ui/public/directives/validate_agg.js +++ b/src/ui/public/directives/validate_agg.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; uiModules diff --git a/src/ui/public/directives/validate_cidr_mask.js b/src/ui/public/directives/validate_cidr_mask.js index a1e37669249bbb..635beda36bc944 100644 --- a/src/ui/public/directives/validate_cidr_mask.js +++ b/src/ui/public/directives/validate_cidr_mask.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { CidrMask } from '../utils/cidr_mask'; import { uiModules } from '../modules'; diff --git a/src/ui/public/directives/validate_date_math.js b/src/ui/public/directives/validate_date_math.js index 8089906c4842ea..bc7277469f9283 100644 --- a/src/ui/public/directives/validate_date_math.js +++ b/src/ui/public/directives/validate_date_math.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import dateMath from '@kbn/datemath'; import { uiModules } from '../modules'; diff --git a/src/ui/public/directives/validate_index_pattern.js b/src/ui/public/directives/validate_index_pattern.js index 2795e3712ecd27..1db3fa05f52b8b 100644 --- a/src/ui/public/directives/validate_index_pattern.js +++ b/src/ui/public/directives/validate_index_pattern.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { uiModules } from '../modules'; // See https://github.com/elastic/elasticsearch/issues/6736 diff --git a/src/ui/public/directives/validate_ip.js b/src/ui/public/directives/validate_ip.js index 58780257f43be9..0120f149c7d476 100644 --- a/src/ui/public/directives/validate_ip.js +++ b/src/ui/public/directives/validate_ip.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Ipv4Address from '../utils/ipv4_address'; import { uiModules } from '../modules'; diff --git a/src/ui/public/directives/validate_json.js b/src/ui/public/directives/validate_json.js index f9f07e4969827b..396cfd13daf88f 100644 --- a/src/ui/public/directives/validate_json.js +++ b/src/ui/public/directives/validate_json.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; const module = uiModules.get('kibana'); diff --git a/src/ui/public/directives/validate_lowercase.js b/src/ui/public/directives/validate_lowercase.js index 5a73843f1009ee..7ba8dd472b4549 100644 --- a/src/ui/public/directives/validate_lowercase.js +++ b/src/ui/public/directives/validate_lowercase.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; uiModules diff --git a/src/ui/public/dirty_prompt/dirty_prompt.factory.js b/src/ui/public/dirty_prompt/dirty_prompt.factory.js index 030f2cd0c858d6..102496f82ea3fa 100644 --- a/src/ui/public/dirty_prompt/dirty_prompt.factory.js +++ b/src/ui/public/dirty_prompt/dirty_prompt.factory.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; import { DirtyPrompt } from './dirty_prompt'; diff --git a/src/ui/public/dirty_prompt/dirty_prompt.js b/src/ui/public/dirty_prompt/dirty_prompt.js index f2bc1f4877c729..af7a73fc43d726 100644 --- a/src/ui/public/dirty_prompt/dirty_prompt.js +++ b/src/ui/public/dirty_prompt/dirty_prompt.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { noop } from 'lodash'; const confirmMessage = `You have unsaved changes. Proceed and discard changes?`; diff --git a/src/ui/public/dirty_prompt/index.js b/src/ui/public/dirty_prompt/index.js index 736fa8521f7710..379d6d00695756 100644 --- a/src/ui/public/dirty_prompt/index.js +++ b/src/ui/public/dirty_prompt/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './dirty_prompt.factory'; diff --git a/src/ui/public/doc_table/__tests__/actions/filter.js b/src/ui/public/doc_table/__tests__/actions/filter.js index d30985403e4e7b..e713d73f5a97fd 100644 --- a/src/ui/public/doc_table/__tests__/actions/filter.js +++ b/src/ui/public/doc_table/__tests__/actions/filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { addFilter } from '../../actions/filter'; import { FilterManagerProvider } from '../../../filter_manager'; import StubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/ui/public/doc_table/__tests__/doc_table.js b/src/ui/public/doc_table/__tests__/doc_table.js index 1553b4fe21091e..7a00effd88f687 100644 --- a/src/ui/public/doc_table/__tests__/doc_table.js +++ b/src/ui/public/doc_table/__tests__/doc_table.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import expect from 'expect.js'; import _ from 'lodash'; diff --git a/src/ui/public/doc_table/__tests__/lib/get_sort.js b/src/ui/public/doc_table/__tests__/lib/get_sort.js index 243dcf73e3f605..3ea586f4579936 100644 --- a/src/ui/public/doc_table/__tests__/lib/get_sort.js +++ b/src/ui/public/doc_table/__tests__/lib/get_sort.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/doc_table/__tests__/lib/rows_headers.js b/src/ui/public/doc_table/__tests__/lib/rows_headers.js index 4235fb1e590161..3e1e03131e635b 100644 --- a/src/ui/public/doc_table/__tests__/lib/rows_headers.js +++ b/src/ui/public/doc_table/__tests__/lib/rows_headers.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import _ from 'lodash'; import sinon from 'sinon'; diff --git a/src/ui/public/doc_table/actions/columns.js b/src/ui/public/doc_table/actions/columns.js index 038f17cd28903d..0d66841ccd2c14 100644 --- a/src/ui/public/doc_table/actions/columns.js +++ b/src/ui/public/doc_table/actions/columns.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function addColumn(columns, columnName) { if (columns.includes(columnName)) { return; diff --git a/src/ui/public/doc_table/actions/filter.js b/src/ui/public/doc_table/actions/filter.js index b9049519e37676..0156089148f4eb 100644 --- a/src/ui/public/doc_table/actions/filter.js +++ b/src/ui/public/doc_table/actions/filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function addFilter(field, values = [], operation, index, state, filterManager) { if (!Array.isArray(values)) { values = [values]; diff --git a/src/ui/public/doc_table/components/table_header.js b/src/ui/public/doc_table/components/table_header.js index 0429997fc05a9b..12966813331ed3 100644 --- a/src/ui/public/doc_table/components/table_header.js +++ b/src/ui/public/doc_table/components/table_header.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import './table_header.less'; import '../../filters/short_dots'; diff --git a/src/ui/public/doc_table/components/table_row.js b/src/ui/public/doc_table/components/table_row.js index 85c3111101bb3d..7a25034628246e 100644 --- a/src/ui/public/doc_table/components/table_row.js +++ b/src/ui/public/doc_table/components/table_row.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import $ from 'jquery'; import rison from 'rison-node'; diff --git a/src/ui/public/doc_table/doc_table.js b/src/ui/public/doc_table/doc_table.js index 599d7002de0c4b..c8d1efea19457c 100644 --- a/src/ui/public/doc_table/doc_table.js +++ b/src/ui/public/doc_table/doc_table.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import html from './doc_table.html'; import { getSort } from './lib/get_sort'; diff --git a/src/ui/public/doc_table/doc_table_strings.js b/src/ui/public/doc_table/doc_table_strings.js index ff63a8b617e581..9b9b1f7cba47a4 100644 --- a/src/ui/public/doc_table/doc_table_strings.js +++ b/src/ui/public/doc_table/doc_table_strings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * A message letting the user know the results that have been retrieved is limited * to a certain size. diff --git a/src/ui/public/doc_table/index.js b/src/ui/public/doc_table/index.js index 278413cfbe5e15..1eb1f10114d532 100644 --- a/src/ui/public/doc_table/index.js +++ b/src/ui/public/doc_table/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './doc_table'; diff --git a/src/ui/public/doc_table/lib/get_sort.js b/src/ui/public/doc_table/lib/get_sort.js index dc4cd0fcce73f4..428dcb846fa797 100644 --- a/src/ui/public/doc_table/lib/get_sort.js +++ b/src/ui/public/doc_table/lib/get_sort.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; /** diff --git a/src/ui/public/doc_title/__tests__/doc_title.js b/src/ui/public/doc_title/__tests__/doc_title.js index 2053d361099dad..4c459a17a6c698 100644 --- a/src/ui/public/doc_title/__tests__/doc_title.js +++ b/src/ui/public/doc_title/__tests__/doc_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import sinon from 'sinon'; import expect from 'expect.js'; diff --git a/src/ui/public/doc_title/doc_title.js b/src/ui/public/doc_title/doc_title.js index 228ec67048e79f..1a0fde0e2486fc 100644 --- a/src/ui/public/doc_title/doc_title.js +++ b/src/ui/public/doc_title/doc_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { uiModules } from '../modules'; diff --git a/src/ui/public/doc_title/index.js b/src/ui/public/doc_title/index.js index f6d1effb96e06f..06018b0c20dcf2 100644 --- a/src/ui/public/doc_title/index.js +++ b/src/ui/public/doc_title/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './doc_title'; export { DocTitleProvider } from './doc_title'; diff --git a/src/ui/public/doc_viewer/__tests__/doc_viewer.js b/src/ui/public/doc_viewer/__tests__/doc_viewer.js index cc87e2af6afc01..141f41393cf2e4 100644 --- a/src/ui/public/doc_viewer/__tests__/doc_viewer.js +++ b/src/ui/public/doc_viewer/__tests__/doc_viewer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import _ from 'lodash'; import expect from 'expect.js'; diff --git a/src/ui/public/doc_viewer/doc_viewer.js b/src/ui/public/doc_viewer/doc_viewer.js index 8a14e2e15e1d71..e9036b9443b7a0 100644 --- a/src/ui/public/doc_viewer/doc_viewer.js +++ b/src/ui/public/doc_viewer/doc_viewer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import { uiModules } from '../modules'; import { DocViewsRegistryProvider } from '../registry/doc_views'; diff --git a/src/ui/public/doc_viewer/index.js b/src/ui/public/doc_viewer/index.js index 3384281b2065b6..791a881fd17bc2 100644 --- a/src/ui/public/doc_viewer/index.js +++ b/src/ui/public/doc_viewer/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './doc_viewer'; diff --git a/src/ui/public/documentation_links/__tests__/documentation_links.js b/src/ui/public/documentation_links/__tests__/documentation_links.js index 47508f53e0148a..7bc119d5ef7d8c 100644 --- a/src/ui/public/documentation_links/__tests__/documentation_links.js +++ b/src/ui/public/documentation_links/__tests__/documentation_links.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { documentationLinks } from '../documentation_links'; import { metadata } from '../../metadata'; diff --git a/src/ui/public/documentation_links/documentation_links.js b/src/ui/public/documentation_links/documentation_links.js index a8e92235a77058..789386f3e0edc5 100644 --- a/src/ui/public/documentation_links/documentation_links.js +++ b/src/ui/public/documentation_links/documentation_links.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { metadata } from '../metadata'; export const DOC_LINK_VERSION = metadata.branch; diff --git a/src/ui/public/documentation_links/get_doc_link.js b/src/ui/public/documentation_links/get_doc_link.js index dcf44a3bfd3018..dc734453f876a2 100644 --- a/src/ui/public/documentation_links/get_doc_link.js +++ b/src/ui/public/documentation_links/get_doc_link.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { get } from 'lodash'; import { documentationLinks } from './documentation_links'; diff --git a/src/ui/public/documentation_links/index.js b/src/ui/public/documentation_links/index.js index 8093a7ce9b8a02..21ca740b216f7d 100644 --- a/src/ui/public/documentation_links/index.js +++ b/src/ui/public/documentation_links/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION, diff --git a/src/ui/public/dom_location.js b/src/ui/public/dom_location.js index 3ae54a0994a1da..39266e0eeaac77 100644 --- a/src/ui/public/dom_location.js +++ b/src/ui/public/dom_location.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function DomLocationProvider($window) { return { reload: function (forceFetch) { diff --git a/src/ui/public/draggable/__tests__/draggable.js b/src/ui/public/draggable/__tests__/draggable.js index 6b083cb8a481a5..8cba8a8ebb11c8 100644 --- a/src/ui/public/draggable/__tests__/draggable.js +++ b/src/ui/public/draggable/__tests__/draggable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/draggable/draggable_container.js b/src/ui/public/draggable/draggable_container.js index 3855a1a557c6a3..22d1aae7fbdde2 100644 --- a/src/ui/public/draggable/draggable_container.js +++ b/src/ui/public/draggable/draggable_container.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import dragula from 'dragula'; import { uiModules } from '../modules'; import { move } from '../utils/collection'; diff --git a/src/ui/public/draggable/draggable_handle.js b/src/ui/public/draggable/draggable_handle.js index aa5f68f47f943a..fe6eef0823b084 100644 --- a/src/ui/public/draggable/draggable_handle.js +++ b/src/ui/public/draggable/draggable_handle.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; uiModules diff --git a/src/ui/public/draggable/draggable_item.js b/src/ui/public/draggable/draggable_item.js index 81beb075d563aa..7e4b7fee63ca1f 100644 --- a/src/ui/public/draggable/draggable_item.js +++ b/src/ui/public/draggable/draggable_item.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import { uiModules } from '../modules'; diff --git a/src/ui/public/elastic_textarea.js b/src/ui/public/elastic_textarea.js index e58f550f7ade02..fcb0775a050d22 100644 --- a/src/ui/public/elastic_textarea.js +++ b/src/ui/public/elastic_textarea.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { uiModules } from './modules'; const NL_RE = /\n/g; diff --git a/src/ui/public/elasticsearch_errors/__tests__/elasticsearch_error.js b/src/ui/public/elasticsearch_errors/__tests__/elasticsearch_error.js index e372c8dc3dc963..bd30781a7d77bb 100644 --- a/src/ui/public/elasticsearch_errors/__tests__/elasticsearch_error.js +++ b/src/ui/public/elasticsearch_errors/__tests__/elasticsearch_error.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { ElasticsearchError } from '../elasticsearch_error'; diff --git a/src/ui/public/elasticsearch_errors/__tests__/is_term_size_zero_error.js b/src/ui/public/elasticsearch_errors/__tests__/is_term_size_zero_error.js index c849c7a59d08aa..6820276ee7df53 100644 --- a/src/ui/public/elasticsearch_errors/__tests__/is_term_size_zero_error.js +++ b/src/ui/public/elasticsearch_errors/__tests__/is_term_size_zero_error.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { isTermSizeZeroError } from '../is_term_size_zero_error'; diff --git a/src/ui/public/elasticsearch_errors/elasticsearch_error.js b/src/ui/public/elasticsearch_errors/elasticsearch_error.js index a20e4e267ff7b8..2275b328751a89 100644 --- a/src/ui/public/elasticsearch_errors/elasticsearch_error.js +++ b/src/ui/public/elasticsearch_errors/elasticsearch_error.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export class ElasticsearchError { diff --git a/src/ui/public/elasticsearch_errors/index.js b/src/ui/public/elasticsearch_errors/index.js index b5fe4727d77ffa..f2929b5b059ac4 100644 --- a/src/ui/public/elasticsearch_errors/index.js +++ b/src/ui/public/elasticsearch_errors/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { ElasticsearchError } from './elasticsearch_error'; export { isTermSizeZeroError } from './is_term_size_zero_error'; diff --git a/src/ui/public/elasticsearch_errors/is_term_size_zero_error.js b/src/ui/public/elasticsearch_errors/is_term_size_zero_error.js index a5afc5f6f583d1..f83eca3d14cfec 100644 --- a/src/ui/public/elasticsearch_errors/is_term_size_zero_error.js +++ b/src/ui/public/elasticsearch_errors/is_term_size_zero_error.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { ElasticsearchError } from './elasticsearch_error'; export function isTermSizeZeroError(error) { diff --git a/src/ui/public/embeddable/embeddable.js b/src/ui/public/embeddable/embeddable.js index 8b1cf57ff5e399..a98c41b13573a0 100644 --- a/src/ui/public/embeddable/embeddable.js +++ b/src/ui/public/embeddable/embeddable.js @@ -1,3 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PropTypes } from 'prop-types'; + /** * @typedef {Object} EmbeddableMetadata - data that does not change over the course of the embeddables life span. * @property {string} title @@ -5,6 +26,12 @@ * @property {IndexPattern} indexPattern */ +export const embeddableShape = PropTypes.shape({ + metadata: PropTypes.object.isRequired, + onContainerStateChanged: PropTypes.func.isRequired, + render: PropTypes.func.isRequired, + destroy: PropTypes.func.isRequired, +}); export class Embeddable { /** @@ -41,8 +68,9 @@ export class Embeddable { /** * @param {Element} domNode - the dom node to mount the rendered embeddable on + * @param {ContainerState} containerState */ - render(/*domNode*/) {} + render(/*domNode, containerState*/) {} destroy() {} } diff --git a/src/ui/public/embeddable/embeddable_factories_registry.js b/src/ui/public/embeddable/embeddable_factories_registry.js index 1b4a291f3fe2ac..7f69625b02248b 100644 --- a/src/ui/public/embeddable/embeddable_factories_registry.js +++ b/src/ui/public/embeddable/embeddable_factories_registry.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiRegistry } from '../registry/_registry'; /** diff --git a/src/ui/public/embeddable/embeddable_factory.js b/src/ui/public/embeddable/embeddable_factory.js index 349d37a45a50d3..bda401b62c2693 100644 --- a/src/ui/public/embeddable/embeddable_factory.js +++ b/src/ui/public/embeddable/embeddable_factory.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * @typedef {Object} EmbeddableState * @property {Object} customization - any customization data that should be stored at the panel level. For diff --git a/src/ui/public/embeddable/index.js b/src/ui/public/embeddable/index.js index d9449c54246604..164d6a4f9252b3 100644 --- a/src/ui/public/embeddable/index.js +++ b/src/ui/public/embeddable/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { EmbeddableFactory } from './embeddable_factory'; -export { Embeddable } from './embeddable'; +export * from './embeddable'; export { EmbeddableFactoriesRegistryProvider } from './embeddable_factories_registry'; diff --git a/src/ui/public/error_allow_explicit_index/error_allow_explicit_index.js b/src/ui/public/error_allow_explicit_index/error_allow_explicit_index.js index 6694071da401cd..f9f02e167d98bd 100644 --- a/src/ui/public/error_allow_explicit_index/error_allow_explicit_index.js +++ b/src/ui/public/error_allow_explicit_index/error_allow_explicit_index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { get } from 'lodash'; import uiRoutes from '../routes'; diff --git a/src/ui/public/error_allow_explicit_index/index.js b/src/ui/public/error_allow_explicit_index/index.js index eee252ff860ef1..a832fde31c987f 100644 --- a/src/ui/public/error_allow_explicit_index/index.js +++ b/src/ui/public/error_allow_explicit_index/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { ErrorAllowExplicitIndexProvider } from './error_allow_explicit_index'; diff --git a/src/ui/public/error_auto_create_index/error_auto_create_index.js b/src/ui/public/error_auto_create_index/error_auto_create_index.js index 24b1e92b8782c4..71fc57ac73e6cb 100644 --- a/src/ui/public/error_auto_create_index/error_auto_create_index.js +++ b/src/ui/public/error_auto_create_index/error_auto_create_index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { get } from 'lodash'; import uiRoutes from '../routes'; diff --git a/src/ui/public/error_auto_create_index/index.js b/src/ui/public/error_auto_create_index/index.js index eafeda9c2e7278..499753246c9f96 100644 --- a/src/ui/public/error_auto_create_index/index.js +++ b/src/ui/public/error_auto_create_index/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { ErrorAutoCreateIndexProvider } from './error_auto_create_index'; diff --git a/src/ui/public/error_url_overflow/__tests__/ie_regex.js b/src/ui/public/error_url_overflow/__tests__/ie_regex.js index e9d5d8ca5faf43..75d114e397fb87 100644 --- a/src/ui/public/error_url_overflow/__tests__/ie_regex.js +++ b/src/ui/public/error_url_overflow/__tests__/ie_regex.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { IE_REGEX } from '../url_overflow_service.js'; diff --git a/src/ui/public/error_url_overflow/error_url_overflow.js b/src/ui/public/error_url_overflow/error_url_overflow.js index 780de70e3fbb12..2ca1049b6e91bf 100644 --- a/src/ui/public/error_url_overflow/error_url_overflow.js +++ b/src/ui/public/error_url_overflow/error_url_overflow.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import uiRoutes from '../routes'; import { KbnUrlProvider } from '../url'; diff --git a/src/ui/public/error_url_overflow/index.js b/src/ui/public/error_url_overflow/index.js index 3f75e4494bf39a..b3e08fd89c76e5 100644 --- a/src/ui/public/error_url_overflow/index.js +++ b/src/ui/public/error_url_overflow/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './error_url_overflow'; export { UrlOverflowServiceProvider } from './url_overflow_service'; diff --git a/src/ui/public/error_url_overflow/url_overflow_service.js b/src/ui/public/error_url_overflow/url_overflow_service.js index addd7e125d6bf8..4e4b2ad634f504 100644 --- a/src/ui/public/error_url_overflow/url_overflow_service.js +++ b/src/ui/public/error_url_overflow/url_overflow_service.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const URL_MAX_IE = 2000; const URL_MAX_OTHERS = 25000; export const IE_REGEX = /(; ?MSIE |Edge\/\d|Trident\/[\d+\.]+;.*rv:*11\.\d+)/; diff --git a/src/ui/public/errors.js b/src/ui/public/errors.js index 2fdff5c6cffac2..d7492d8da3aee7 100644 --- a/src/ui/public/errors.js +++ b/src/ui/public/errors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import { createLegacyClass } from './utils/legacy_class'; diff --git a/src/ui/public/es.js b/src/ui/public/es.js index 5308bf491b00a5..d1204f8316f0d7 100644 --- a/src/ui/public/es.js +++ b/src/ui/public/es.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * @name es * diff --git a/src/ui/public/events.js b/src/ui/public/events.js index edfeb2c48bdf73..b8ad36ad15e5a3 100644 --- a/src/ui/public/events.js +++ b/src/ui/public/events.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * @name Events * diff --git a/src/ui/public/factories/__tests__/base_object.js b/src/ui/public/factories/__tests__/base_object.js index c761e9e586b5b0..913f647db33601 100644 --- a/src/ui/public/factories/__tests__/base_object.js +++ b/src/ui/public/factories/__tests__/base_object.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import '../../private'; diff --git a/src/ui/public/factories/__tests__/events.js b/src/ui/public/factories/__tests__/events.js index c6d8ce4e173d8c..c9ba7f5798544b 100644 --- a/src/ui/public/factories/__tests__/events.js +++ b/src/ui/public/factories/__tests__/events.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import sinon from 'sinon'; diff --git a/src/ui/public/fancy_forms/__tests__/fancy_forms.js b/src/ui/public/fancy_forms/__tests__/fancy_forms.js index d76e65739f12b8..04fcd5717e112a 100644 --- a/src/ui/public/fancy_forms/__tests__/fancy_forms.js +++ b/src/ui/public/fancy_forms/__tests__/fancy_forms.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; import $ from 'jquery'; diff --git a/src/ui/public/fancy_forms/__tests__/nested_fancy_forms.js b/src/ui/public/fancy_forms/__tests__/nested_fancy_forms.js index 79cabc279b1a86..005e6441b03a8e 100644 --- a/src/ui/public/fancy_forms/__tests__/nested_fancy_forms.js +++ b/src/ui/public/fancy_forms/__tests__/nested_fancy_forms.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; import sinon from 'sinon'; diff --git a/src/ui/public/fancy_forms/fancy_forms.js b/src/ui/public/fancy_forms/fancy_forms.js index cb6ae667b8bd73..4d461f657be718 100644 --- a/src/ui/public/fancy_forms/fancy_forms.js +++ b/src/ui/public/fancy_forms/fancy_forms.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../modules'; import { decorateFormController } from './kbn_form_controller'; diff --git a/src/ui/public/fancy_forms/index.js b/src/ui/public/fancy_forms/index.js index 38cac2fc5a6b18..927e6d69e3c8a3 100644 --- a/src/ui/public/fancy_forms/index.js +++ b/src/ui/public/fancy_forms/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './fancy_forms'; diff --git a/src/ui/public/fancy_forms/kbn_form_controller.js b/src/ui/public/fancy_forms/kbn_form_controller.js index fd29058e8c1dd6..f376d8dfe34606 100644 --- a/src/ui/public/fancy_forms/kbn_form_controller.js +++ b/src/ui/public/fancy_forms/kbn_form_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function decorateFormController($delegate, $injector) { const [directive] = $delegate; const FormController = directive.controller; diff --git a/src/ui/public/fancy_forms/kbn_model_controller.js b/src/ui/public/fancy_forms/kbn_model_controller.js index 4345f20c5de1ac..ce4e8a8230be66 100644 --- a/src/ui/public/fancy_forms/kbn_model_controller.js +++ b/src/ui/public/fancy_forms/kbn_model_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function decorateModelController($delegate, $injector) { const [directive] = $delegate; const ModelController = directive.controller; diff --git a/src/ui/public/field_editor/__tests__/field_editor.js b/src/ui/public/field_editor/__tests__/field_editor.js index d42c823075dc04..7cc9d538c00e61 100644 --- a/src/ui/public/field_editor/__tests__/field_editor.js +++ b/src/ui/public/field_editor/__tests__/field_editor.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/field_editor/field_editor.js b/src/ui/public/field_editor/field_editor.js index 243bcf497453b6..a43250b3216d81 100644 --- a/src/ui/public/field_editor/field_editor.js +++ b/src/ui/public/field_editor/field_editor.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import '../field_format_editor'; import _ from 'lodash'; @@ -72,7 +91,7 @@ uiModules } if (!self.selectedFormatId) { - delete indexPattern.fieldFormatMap[field.name]; + indexPattern.fieldFormatMap[field.name] = {}; } else { indexPattern.fieldFormatMap[field.name] = self.field.format; } @@ -116,12 +135,20 @@ uiModules const changedFormat = cur !== prev; const missingFormat = cur && (!format || format.type.id !== cur); - if (!changedFormat || !missingFormat) return; + if (!changedFormat || !missingFormat) { + return; + } // reset to the defaults, but make sure it's an object const FieldFormat = getFieldFormatType(); const paramDefaults = new FieldFormat({}, getConfig).getParamDefaults(); + const currentFormatParams = self.formatParams; self.formatParams = _.assign({}, _.cloneDeep(paramDefaults)); + // If there are no current or new params, the watch will not trigger + // so manually update the format here + if (_.size(currentFormatParams) === 0 && _.size(self.formatParams) === 0) { + self.field.format = new FieldFormat(self.formatParams, getConfig); + } }); $scope.$watch('editor.formatParams', function () { diff --git a/src/ui/public/field_editor/index.js b/src/ui/public/field_editor/index.js index 7e26c1dcdc21af..d6f4251fa0a6ea 100644 --- a/src/ui/public/field_editor/index.js +++ b/src/ui/public/field_editor/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './field_editor'; diff --git a/src/ui/public/field_format_editor/editors/color/color.js b/src/ui/public/field_format_editor/editors/color/color.js index 7d9e02ffcd545a..60c083b4a15a50 100644 --- a/src/ui/public/field_format_editor/editors/color/color.js +++ b/src/ui/public/field_format_editor/editors/color/color.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './color.less'; import colorTemplate from './color.html'; import { DEFAULT_COLOR } from '../../../../../core_plugins/kibana/common/field_formats/types/color_default'; diff --git a/src/ui/public/field_format_editor/editors/color/index.js b/src/ui/public/field_format_editor/editors/color/index.js index 39752028181456..5f26c0bea6ab73 100644 --- a/src/ui/public/field_format_editor/editors/color/index.js +++ b/src/ui/public/field_format_editor/editors/color/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { colorEditor } from './color'; diff --git a/src/ui/public/field_format_editor/editors/date/date.js b/src/ui/public/field_format_editor/editors/date/date.js index d41c8c5ad50e5f..c35b9ffcfb306f 100644 --- a/src/ui/public/field_format_editor/editors/date/date.js +++ b/src/ui/public/field_format_editor/editors/date/date.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import dateTemplate from './date.html'; import moment from 'moment'; diff --git a/src/ui/public/field_format_editor/editors/date/index.js b/src/ui/public/field_format_editor/editors/date/index.js index 8ce6806c6a8f12..b859ee5030c0df 100644 --- a/src/ui/public/field_format_editor/editors/date/index.js +++ b/src/ui/public/field_format_editor/editors/date/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { dateEditor } from './date'; diff --git a/src/ui/public/field_format_editor/editors/duration/duration.js b/src/ui/public/field_format_editor/editors/duration/duration.js index 2ec1cbf2415a4a..9909ca74236efa 100644 --- a/src/ui/public/field_format_editor/editors/duration/duration.js +++ b/src/ui/public/field_format_editor/editors/duration/duration.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './duration.less'; import durationTemplate from './duration.html'; diff --git a/src/ui/public/field_format_editor/editors/duration/index.js b/src/ui/public/field_format_editor/editors/duration/index.js index 8de49d818f83bb..71078715bf3a34 100644 --- a/src/ui/public/field_format_editor/editors/duration/index.js +++ b/src/ui/public/field_format_editor/editors/duration/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { durationEditor } from './duration'; diff --git a/src/ui/public/field_format_editor/editors/numeral/bytes.js b/src/ui/public/field_format_editor/editors/numeral/bytes.js index ee4f2b12843eb8..f086464b0edbdf 100644 --- a/src/ui/public/field_format_editor/editors/numeral/bytes.js +++ b/src/ui/public/field_format_editor/editors/numeral/bytes.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import numeralTemplate from './numeral.html'; export function bytesEditor() { diff --git a/src/ui/public/field_format_editor/editors/numeral/number.js b/src/ui/public/field_format_editor/editors/numeral/number.js index 65f437655b463b..ddc1e68af5f798 100644 --- a/src/ui/public/field_format_editor/editors/numeral/number.js +++ b/src/ui/public/field_format_editor/editors/numeral/number.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import numeralTemplate from './numeral.html'; export function numberEditor() { diff --git a/src/ui/public/field_format_editor/editors/numeral/percent.js b/src/ui/public/field_format_editor/editors/numeral/percent.js index 3aaf46ab9d7b4a..75984eddc281a5 100644 --- a/src/ui/public/field_format_editor/editors/numeral/percent.js +++ b/src/ui/public/field_format_editor/editors/numeral/percent.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import numeralTemplate from './numeral.html'; export function percentEditor() { diff --git a/src/ui/public/field_format_editor/editors/string/index.js b/src/ui/public/field_format_editor/editors/string/index.js index 414458b8ed6850..4971d835e88a35 100644 --- a/src/ui/public/field_format_editor/editors/string/index.js +++ b/src/ui/public/field_format_editor/editors/string/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { stringEditor } from './string'; diff --git a/src/ui/public/field_format_editor/editors/string/string.js b/src/ui/public/field_format_editor/editors/string/string.js index 4c8788ac493d4e..00efd11d44f028 100644 --- a/src/ui/public/field_format_editor/editors/string/string.js +++ b/src/ui/public/field_format_editor/editors/string/string.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import stringTemplate from './string.html'; export function stringEditor() { diff --git a/src/ui/public/field_format_editor/editors/truncate/index.js b/src/ui/public/field_format_editor/editors/truncate/index.js index d8762880564714..7d7b2af1794a70 100644 --- a/src/ui/public/field_format_editor/editors/truncate/index.js +++ b/src/ui/public/field_format_editor/editors/truncate/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { truncateEditor } from './truncate'; diff --git a/src/ui/public/field_format_editor/editors/truncate/truncate.js b/src/ui/public/field_format_editor/editors/truncate/truncate.js index d58e0eeb13934f..528fffb24e8379 100644 --- a/src/ui/public/field_format_editor/editors/truncate/truncate.js +++ b/src/ui/public/field_format_editor/editors/truncate/truncate.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import truncateTemplate from './truncate.html'; import largeString from './large.html'; diff --git a/src/ui/public/field_format_editor/editors/url/icons/index.js b/src/ui/public/field_format_editor/editors/url/icons/index.js index 3c663303977f16..7e251d7cae7127 100644 --- a/src/ui/public/field_format_editor/editors/url/icons/index.js +++ b/src/ui/public/field_format_editor/editors/url/icons/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import '!!file-loader?name=[path][name].[ext]!ui/field_format_editor/editors/url/icons/go.png'; import '!!file-loader?name=[path][name].[ext]!ui/field_format_editor/editors/url/icons/stop.png'; import '!!file-loader?name=[path][name].[ext]!ui/field_format_editor/editors/url/icons/de.png'; diff --git a/src/ui/public/field_format_editor/editors/url/index.js b/src/ui/public/field_format_editor/editors/url/index.js index 7f58a44a23caa8..157ab469095125 100644 --- a/src/ui/public/field_format_editor/editors/url/index.js +++ b/src/ui/public/field_format_editor/editors/url/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { urlEditor } from './url'; diff --git a/src/ui/public/field_format_editor/editors/url/url.js b/src/ui/public/field_format_editor/editors/url/url.js index d2c26669248ba0..938dd4038c3942 100644 --- a/src/ui/public/field_format_editor/editors/url/url.js +++ b/src/ui/public/field_format_editor/editors/url/url.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import urlTemplate from './url.html'; import './icons'; diff --git a/src/ui/public/field_format_editor/field_format_editor.js b/src/ui/public/field_format_editor/field_format_editor.js index c7d769c669bd2c..9d94fc23882b65 100644 --- a/src/ui/public/field_format_editor/field_format_editor.js +++ b/src/ui/public/field_format_editor/field_format_editor.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './pattern/pattern'; import './samples/samples'; import _ from 'lodash'; diff --git a/src/ui/public/field_format_editor/index.js b/src/ui/public/field_format_editor/index.js index d2e94738c0f4ab..28871f415f6010 100644 --- a/src/ui/public/field_format_editor/index.js +++ b/src/ui/public/field_format_editor/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './field_format_editor'; diff --git a/src/ui/public/field_format_editor/pattern/index.js b/src/ui/public/field_format_editor/pattern/index.js index 540bdd14d1a469..768a64a34cc98e 100644 --- a/src/ui/public/field_format_editor/pattern/index.js +++ b/src/ui/public/field_format_editor/pattern/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './pattern'; diff --git a/src/ui/public/field_format_editor/pattern/pattern.js b/src/ui/public/field_format_editor/pattern/pattern.js index f6c446c1c2d4e5..bd438833430471 100644 --- a/src/ui/public/field_format_editor/pattern/pattern.js +++ b/src/ui/public/field_format_editor/pattern/pattern.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import '../samples/samples'; import { uiModules } from '../../modules'; import patternTemplate from './pattern.html'; diff --git a/src/ui/public/field_format_editor/register.js b/src/ui/public/field_format_editor/register.js index 3a28eacf3b0a45..4ed528eb1f5309 100644 --- a/src/ui/public/field_format_editor/register.js +++ b/src/ui/public/field_format_editor/register.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { RegistryFieldFormatEditorsProvider } from '../registry/field_format_editors'; import { bytesEditor } from './editors/numeral/bytes'; import { colorEditor } from './editors/color/color'; diff --git a/src/ui/public/field_format_editor/samples/index.js b/src/ui/public/field_format_editor/samples/index.js index 161a81bd50b483..0a9b253d3b9b49 100644 --- a/src/ui/public/field_format_editor/samples/index.js +++ b/src/ui/public/field_format_editor/samples/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './samples'; diff --git a/src/ui/public/field_format_editor/samples/samples.js b/src/ui/public/field_format_editor/samples/samples.js index 521933a99ea610..ace7a731c0755b 100644 --- a/src/ui/public/field_format_editor/samples/samples.js +++ b/src/ui/public/field_format_editor/samples/samples.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { uiModules } from '../../modules'; import samplesTemplate from './samples.html'; diff --git a/src/ui/public/field_wildcard/__tests__/field_wildcard.js b/src/ui/public/field_wildcard/__tests__/field_wildcard.js index b290df4a4d5b7c..5b588726204eda 100644 --- a/src/ui/public/field_wildcard/__tests__/field_wildcard.js +++ b/src/ui/public/field_wildcard/__tests__/field_wildcard.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/field_wildcard/field_wildcard.js b/src/ui/public/field_wildcard/field_wildcard.js index dcb387fe0b89f8..a07ee552483c69 100644 --- a/src/ui/public/field_wildcard/field_wildcard.js +++ b/src/ui/public/field_wildcard/field_wildcard.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { escapeRegExp, memoize } from 'lodash'; export function FieldWildcardProvider(config) { diff --git a/src/ui/public/field_wildcard/index.js b/src/ui/public/field_wildcard/index.js index dccbb2f5b4e6d2..d03643f8804d89 100644 --- a/src/ui/public/field_wildcard/index.js +++ b/src/ui/public/field_wildcard/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { FieldWildcardProvider } from './field_wildcard'; diff --git a/src/ui/public/filter_bar/__tests__/_add_filters.js b/src/ui/public/filter_bar/__tests__/_add_filters.js index 3e7df03bacef29..a744992511432b 100644 --- a/src/ui/public/filter_bar/__tests__/_add_filters.js +++ b/src/ui/public/filter_bar/__tests__/_add_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import sinon from 'sinon'; import expect from 'expect.js'; diff --git a/src/ui/public/filter_bar/__tests__/_get_filters.js b/src/ui/public/filter_bar/__tests__/_get_filters.js index e05614f5ba07e9..5b0abd9efcdf43 100644 --- a/src/ui/public/filter_bar/__tests__/_get_filters.js +++ b/src/ui/public/filter_bar/__tests__/_get_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/filter_bar/__tests__/_invert_filters.js b/src/ui/public/filter_bar/__tests__/_invert_filters.js index e1ca6615dc0c6c..61024873ecb1fd 100644 --- a/src/ui/public/filter_bar/__tests__/_invert_filters.js +++ b/src/ui/public/filter_bar/__tests__/_invert_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import sinon from 'sinon'; import expect from 'expect.js'; diff --git a/src/ui/public/filter_bar/__tests__/_pin_filters.js b/src/ui/public/filter_bar/__tests__/_pin_filters.js index dc293ece017282..f84d07effc4cad 100644 --- a/src/ui/public/filter_bar/__tests__/_pin_filters.js +++ b/src/ui/public/filter_bar/__tests__/_pin_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import sinon from 'sinon'; import expect from 'expect.js'; diff --git a/src/ui/public/filter_bar/__tests__/_remove_filters.js b/src/ui/public/filter_bar/__tests__/_remove_filters.js index c3a8143532448d..69a0942e205a27 100644 --- a/src/ui/public/filter_bar/__tests__/_remove_filters.js +++ b/src/ui/public/filter_bar/__tests__/_remove_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import sinon from 'sinon'; import expect from 'expect.js'; diff --git a/src/ui/public/filter_bar/__tests__/_toggle_filters.js b/src/ui/public/filter_bar/__tests__/_toggle_filters.js index 82d36e01fbfefc..d4205d542bdaaa 100644 --- a/src/ui/public/filter_bar/__tests__/_toggle_filters.js +++ b/src/ui/public/filter_bar/__tests__/_toggle_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/filter_bar/__tests__/filter_bar.js b/src/ui/public/filter_bar/__tests__/filter_bar.js index 8c94c08e639f3a..b06de1d8b15537 100644 --- a/src/ui/public/filter_bar/__tests__/filter_bar.js +++ b/src/ui/public/filter_bar/__tests__/filter_bar.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import ngMock from 'ng_mock'; import expect from 'expect.js'; @@ -114,5 +133,96 @@ describe('Filter Bar Directive', function () { expect($scope.addFilters.called).to.be(true); }); }); + + describe('show and hide filters', function () { + let scope; + + beforeEach(() => { + scope = $rootScope.$new(); + }); + + function create(attrs) { + const template = ` +
+ + +
`; + + const element = $compile(template)(scope); + + scope.$apply(() => { + Object.assign(scope, attrs); + }); + + return element; + } + + + describe('collapse filters', function () { + let element; + + beforeEach(function () { + element = create({ + filterNavToggle: { + isOpen: false + } + }); + }); + + it('should be able to collapse filters', function () { + expect(element.hasClass('filter-panel-close')).to.be(true); + }); + + it('should be able to see `actions`', function () { + expect(element.find('.filter-link.pull-right').hasClass('action-show')).to.be(true); + }); + + it('should be able to view the same button for `expand`', function () { + expect(element.find('.filter-nav-link__icon').hasClass('filter-nav-link--close')).to.be(true); + }); + }); + + describe('expand filters', function () { + let element; + + beforeEach(function () { + element = create({ + filterNavToggle: { + isOpen: true + } + }); + }); + + it('should be able to expand filters', function () { + expect(element.hasClass('filter-panel-close')).to.be(false); + }); + + it('should be able to view the `actions` at the bottom of the filter-bar', function () { + expect(element.find('.filter-link.pull-right').hasClass('action-show')).to.be(false); + }); + + it('should be able to view the same button for `collapse`', function () { + expect(element.find('.filter-nav-link__icon').hasClass('filter-nav-link--close')).to.be(false); + }); + }); + + }); + }); }); diff --git a/src/ui/public/filter_bar/__tests__/filter_bar_click_handler.js b/src/ui/public/filter_bar/__tests__/filter_bar_click_handler.js index 76582fa3caae20..612956327c18fe 100644 --- a/src/ui/public/filter_bar/__tests__/filter_bar_click_handler.js +++ b/src/ui/public/filter_bar/__tests__/filter_bar_click_handler.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; @@ -39,7 +58,7 @@ describe('filterBarClickHandler', function () { }; })); - afterEach(function () { + beforeEach(function () { toastNotifications.list.splice(0); }); diff --git a/src/ui/public/filter_bar/__tests__/push_filter.js b/src/ui/public/filter_bar/__tests__/push_filter.js index d45e2a107acd8e..7d8e38b8af7f8b 100644 --- a/src/ui/public/filter_bar/__tests__/push_filter.js +++ b/src/ui/public/filter_bar/__tests__/push_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarPushFilterProvider } from '../push_filter'; diff --git a/src/ui/public/filter_bar/__tests__/query_filter.js b/src/ui/public/filter_bar/__tests__/query_filter.js index fe87dc0df0b6c1..e3d8a0e8b61d27 100644 --- a/src/ui/public/filter_bar/__tests__/query_filter.js +++ b/src/ui/public/filter_bar/__tests__/query_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import './_get_filters'; diff --git a/src/ui/public/filter_bar/filter_bar.html b/src/ui/public/filter_bar/filter_bar.html index ac2ca4cad49e11..30222bfa1977a6 100644 --- a/src/ui/public/filter_bar/filter_bar.html +++ b/src/ui/public/filter_bar/filter_bar.html @@ -26,17 +26,20 @@
- +
+ +
+ +
{ + const pill = $elem.find('filter-pill'); + return pill[pill.length - 1].offsetTop > 10; + }; + + $scope.filterNavToggle = { + isOpen: true, + tooltipContent: 'Collapse to hide filters' + }; + + $scope.toggleFilterShown = () => { + const collapser = $elem.find('.filter-nav-link__collapser'); + const filterPanelPill = $elem.find('.filter-panel__pill'); + if ($scope.filterNavToggle.isOpen) { + $scope.filterNavToggle.tooltipContent = 'Expand to show filters'; + collapser.attr('aria-expanded', 'false'); + filterPanelPill.attr('style', 'width: calc(100% - 80px)'); + } else { + $scope.filterNavToggle.tooltipContent = 'Collapse to hide filters'; + collapser.attr('aria-expanded', 'true'); + filterPanelPill.attr('style', 'width: auto'); + } + + $scope.filterNavToggle.isOpen = !$scope.filterNavToggle.isOpen; + }; + $scope.applyFilters = function (filters) { addAndInvertFilters(filterAppliedAndUnwrap(filters)); $scope.newFilters = []; diff --git a/src/ui/public/filter_bar/filter_bar.less b/src/ui/public/filter_bar/filter_bar.less index c3aea5dd81f6b7..e2d7251d2e4bf3 100644 --- a/src/ui/public/filter_bar/filter_bar.less +++ b/src/ui/public/filter_bar/filter_bar.less @@ -49,6 +49,25 @@ filter-bar { } } +.filter-panel { + position: relative; + + .filter-panel__pill { + display: inline; + } + +} + +.filter-panel--close { + max-height: 36px; + overflow-y: hidden; + min-width: 250px; + + .filter-panel__pill { + display: inline-block; + } +} + .filter-bar { padding: 6px 10px 1px 10px; background: @filter-bar-bar-bg; @@ -76,6 +95,30 @@ filter-bar { line-height: 1.5; } + .action-show { + position: absolute; + right: 30px; + bottom: 0; + } + + .filter-nav-link__icon { + display: inline; + position: absolute; + top: 10px; + right: 10px; + opacity: 0.75; + font-size: 16px; + + &:hover { + opacity: 1; + } + + .filter-nav-link__collapser { + border: none; + line-height: 1; + } + } + .filter { position: relative; display: inline-block; diff --git a/src/ui/public/filter_bar/filter_bar_click_handler.js b/src/ui/public/filter_bar/filter_bar_click_handler.js index 7bce1d293053d1..060be79644d381 100644 --- a/src/ui/public/filter_bar/filter_bar_click_handler.js +++ b/src/ui/public/filter_bar/filter_bar_click_handler.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { dedupFilters } from './lib/dedup_filters'; import { uniqFilters } from './lib/uniq_filters'; diff --git a/src/ui/public/filter_bar/filter_pill/filter_pill.js b/src/ui/public/filter_bar/filter_pill/filter_pill.js index f7479195a4ec88..03b19427af9300 100644 --- a/src/ui/public/filter_bar/filter_pill/filter_pill.js +++ b/src/ui/public/filter_bar/filter_pill/filter_pill.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import template from './filter_pill.html'; import { uiModules } from '../../modules'; diff --git a/src/ui/public/filter_bar/filter_pill/index.js b/src/ui/public/filter_bar/filter_pill/index.js index 29bedd05e69c22..3db610588eb754 100644 --- a/src/ui/public/filter_bar/filter_pill/index.js +++ b/src/ui/public/filter_bar/filter_pill/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './filter_pill'; diff --git a/src/ui/public/filter_bar/index.js b/src/ui/public/filter_bar/index.js index 601279e0714180..082a17b501ed97 100644 --- a/src/ui/public/filter_bar/index.js +++ b/src/ui/public/filter_bar/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './filter_bar'; // directive export { disableFilter, enableFilter, toggleFilterDisabled } from './lib/disable_filter'; diff --git a/src/ui/public/filter_bar/lib/__tests__/change_time_filter.js b/src/ui/public/filter_bar/lib/__tests__/change_time_filter.js index 8d44f06735d89b..a524cd909bb576 100644 --- a/src/ui/public/filter_bar/lib/__tests__/change_time_filter.js +++ b/src/ui/public/filter_bar/lib/__tests__/change_time_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import moment from 'moment'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/filter_bar/lib/__tests__/dedup_filters.js b/src/ui/public/filter_bar/lib/__tests__/dedup_filters.js index b02ae547c13488..33b22efa4abbab 100644 --- a/src/ui/public/filter_bar/lib/__tests__/dedup_filters.js +++ b/src/ui/public/filter_bar/lib/__tests__/dedup_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { dedupFilters } from '../dedup_filters'; import expect from 'expect.js'; diff --git a/src/ui/public/filter_bar/lib/__tests__/disable_filter.js b/src/ui/public/filter_bar/lib/__tests__/disable_filter.js index 0d0a2faa60c99a..2541ec6cacae08 100644 --- a/src/ui/public/filter_bar/lib/__tests__/disable_filter.js +++ b/src/ui/public/filter_bar/lib/__tests__/disable_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { diff --git a/src/ui/public/filter_bar/lib/__tests__/extract_time_filter.js b/src/ui/public/filter_bar/lib/__tests__/extract_time_filter.js index f00d46d59aae39..830b9660b97152 100644 --- a/src/ui/public/filter_bar/lib/__tests__/extract_time_filter.js +++ b/src/ui/public/filter_bar/lib/__tests__/extract_time_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibExtractTimeFilterProvider } from '../extract_time_filter'; diff --git a/src/ui/public/filter_bar/lib/__tests__/filter_applied_and_unwrap.js b/src/ui/public/filter_bar/lib/__tests__/filter_applied_and_unwrap.js index 27282414c3721e..819035452837e3 100644 --- a/src/ui/public/filter_bar/lib/__tests__/filter_applied_and_unwrap.js +++ b/src/ui/public/filter_bar/lib/__tests__/filter_applied_and_unwrap.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { filterAppliedAndUnwrap } from '../filter_applied_and_unwrap'; diff --git a/src/ui/public/filter_bar/lib/__tests__/filter_out_time_based_filter.js b/src/ui/public/filter_bar/lib/__tests__/filter_out_time_based_filter.js index 1c2219359539d7..ec0d6092ad3ab2 100644 --- a/src/ui/public/filter_bar/lib/__tests__/filter_out_time_based_filter.js +++ b/src/ui/public/filter_bar/lib/__tests__/filter_out_time_based_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibFilterOutTimeBasedFilterProvider } from '../filter_out_time_based_filter'; diff --git a/src/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js b/src/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js index f0f73b1f0b51ca..dde12dc59611d4 100644 --- a/src/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js +++ b/src/ui/public/filter_bar/lib/__tests__/generate_mapping_chain.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js b/src/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js index c653c7613ed4fd..84a142b766d420 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_and_flatten_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibMapAndFlattenFiltersProvider } from '../map_and_flatten_filters'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_default.js b/src/ui/public/filter_bar/lib/__tests__/map_default.js index fb195ee50c6638..52400ceeb2a21d 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_default.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_default.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibMapDefaultProvider } from '../map_default'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_exists.js b/src/ui/public/filter_bar/lib/__tests__/map_exists.js index 991ec0bc0422a7..8a36d5cf82af6d 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_exists.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_exists.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibMapExistsProvider } from '../map_exists'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_filter.js b/src/ui/public/filter_bar/lib/__tests__/map_filter.js index 555eec5502496e..31deb84b870ca0 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_filter.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibMapFilterProvider } from '../map_filter'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js b/src/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js index 594b9996f9464e..4f1657a7f961f1 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_flatten_and_wrap_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import expect from 'expect.js'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js b/src/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js index bdc9efc0945d68..f612299c7e5e83 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_geo_bounding_box.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibMapGeoBoundingBoxProvider } from '../map_geo_bounding_box'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js b/src/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js index 9d8b7c76e00b8b..bb66f97fa54633 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_geo_polygon.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibMapGeoPolygonProvider } from '../map_geo_polygon'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_match_all.js b/src/ui/public/filter_bar/lib/__tests__/map_match_all.js index aa7d601408495b..d092e6d7979c44 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_match_all.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_match_all.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibMapMatchAllProvider } from '../map_match_all'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_missing.js b/src/ui/public/filter_bar/lib/__tests__/map_missing.js index 2f126f20a4982a..551898c8fbdda2 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_missing.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_missing.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; import { FilterBarLibMapMissingProvider } from '../map_missing'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_phrase.js b/src/ui/public/filter_bar/lib/__tests__/map_phrase.js index 7fa536d41d7f6e..83ac88bddcfaa4 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_phrase.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_phrase.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibMapPhraseProvider } from '../map_phrase'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_query_string.js b/src/ui/public/filter_bar/lib/__tests__/map_query_string.js index 0e4d5d89428d02..a0d7a8f5b2876e 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_query_string.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_query_string.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibMapQueryStringProvider } from '../map_query_string'; diff --git a/src/ui/public/filter_bar/lib/__tests__/map_range.js b/src/ui/public/filter_bar/lib/__tests__/map_range.js index 6eb37989a836a6..2a23b6001c97e6 100644 --- a/src/ui/public/filter_bar/lib/__tests__/map_range.js +++ b/src/ui/public/filter_bar/lib/__tests__/map_range.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { FilterBarLibMapRangeProvider } from '../map_range'; diff --git a/src/ui/public/filter_bar/lib/__tests__/only_disabled.js b/src/ui/public/filter_bar/lib/__tests__/only_disabled.js index a5e5c28a148554..7bc9c6c58d2edb 100644 --- a/src/ui/public/filter_bar/lib/__tests__/only_disabled.js +++ b/src/ui/public/filter_bar/lib/__tests__/only_disabled.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { onlyDisabled } from '../only_disabled'; import expect from 'expect.js'; diff --git a/src/ui/public/filter_bar/lib/__tests__/uniq_filters.js b/src/ui/public/filter_bar/lib/__tests__/uniq_filters.js index 22495e2a258228..e42cc71485ab5b 100644 --- a/src/ui/public/filter_bar/lib/__tests__/uniq_filters.js +++ b/src/ui/public/filter_bar/lib/__tests__/uniq_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uniqFilters } from '../uniq_filters'; import expect from 'expect.js'; diff --git a/src/ui/public/filter_bar/lib/change_time_filter.js b/src/ui/public/filter_bar/lib/change_time_filter.js index b8c91c44f20e44..f459cdc4307574 100644 --- a/src/ui/public/filter_bar/lib/change_time_filter.js +++ b/src/ui/public/filter_bar/lib/change_time_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import moment from 'moment'; import _ from 'lodash'; diff --git a/src/ui/public/filter_bar/lib/compare_filters.js b/src/ui/public/filter_bar/lib/compare_filters.js index 4f8727d152adff..f9f11f96d194fd 100644 --- a/src/ui/public/filter_bar/lib/compare_filters.js +++ b/src/ui/public/filter_bar/lib/compare_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; let excludedAttributes; let comparators; diff --git a/src/ui/public/filter_bar/lib/dedup_filters.js b/src/ui/public/filter_bar/lib/dedup_filters.js index 8f77e7c291de9f..055e23ab2f25fa 100644 --- a/src/ui/public/filter_bar/lib/dedup_filters.js +++ b/src/ui/public/filter_bar/lib/dedup_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { compareFilters } from './compare_filters'; diff --git a/src/ui/public/filter_bar/lib/disable_filter.js b/src/ui/public/filter_bar/lib/disable_filter.js index 099af1b9b19b3e..815bc4eb2a83ac 100644 --- a/src/ui/public/filter_bar/lib/disable_filter.js +++ b/src/ui/public/filter_bar/lib/disable_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function disableFilter(filter) { return setFilterDisabled(filter, true); } diff --git a/src/ui/public/filter_bar/lib/extract_time_filter.js b/src/ui/public/filter_bar/lib/extract_time_filter.js index 8a615ac7bb93cf..8d641ef0734687 100644 --- a/src/ui/public/filter_bar/lib/extract_time_filter.js +++ b/src/ui/public/filter_bar/lib/extract_time_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function FilterBarLibExtractTimeFilterProvider(courier, Promise) { diff --git a/src/ui/public/filter_bar/lib/filter_applied_and_unwrap.js b/src/ui/public/filter_bar/lib/filter_applied_and_unwrap.js index a6dcd0a8551622..843ff6daf10494 100644 --- a/src/ui/public/filter_bar/lib/filter_applied_and_unwrap.js +++ b/src/ui/public/filter_bar/lib/filter_applied_and_unwrap.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function filterAppliedAndUnwrap(filters) { diff --git a/src/ui/public/filter_bar/lib/filter_out_time_based_filter.js b/src/ui/public/filter_bar/lib/filter_out_time_based_filter.js index 542792d20e8299..53b9c86e6bd35d 100644 --- a/src/ui/public/filter_bar/lib/filter_out_time_based_filter.js +++ b/src/ui/public/filter_bar/lib/filter_out_time_based_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function FilterBarLibFilterOutTimeBasedFilterProvider(courier, Promise) { diff --git a/src/ui/public/filter_bar/lib/generate_mapping_chain.js b/src/ui/public/filter_bar/lib/generate_mapping_chain.js index 09668a29cc3db7..35471ff6ff8d0a 100644 --- a/src/ui/public/filter_bar/lib/generate_mapping_chain.js +++ b/src/ui/public/filter_bar/lib/generate_mapping_chain.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function FilterBarLibGenerateMappingChainProvider(Promise) { const noop = function () { diff --git a/src/ui/public/filter_bar/lib/map_and_flatten_filters.js b/src/ui/public/filter_bar/lib/map_and_flatten_filters.js index bb917cb2174b36..efc8305783fbb8 100644 --- a/src/ui/public/filter_bar/lib/map_and_flatten_filters.js +++ b/src/ui/public/filter_bar/lib/map_and_flatten_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { FilterBarLibMapFilterProvider } from './map_filter'; diff --git a/src/ui/public/filter_bar/lib/map_default.js b/src/ui/public/filter_bar/lib/map_default.js index 292bf92faef14b..5eabd1b79e251e 100644 --- a/src/ui/public/filter_bar/lib/map_default.js +++ b/src/ui/public/filter_bar/lib/map_default.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import _ from 'lodash'; diff --git a/src/ui/public/filter_bar/lib/map_exists.js b/src/ui/public/filter_bar/lib/map_exists.js index 36ada1d127dda4..89a09ac9e0f418 100644 --- a/src/ui/public/filter_bar/lib/map_exists.js +++ b/src/ui/public/filter_bar/lib/map_exists.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function FilterBarLibMapExistsProvider(Promise) { return function (filter) { if (filter.exists) { diff --git a/src/ui/public/filter_bar/lib/map_filter.js b/src/ui/public/filter_bar/lib/map_filter.js index 50c080098ae6f0..c7bdd9befee802 100644 --- a/src/ui/public/filter_bar/lib/map_filter.js +++ b/src/ui/public/filter_bar/lib/map_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { FilterBarLibGenerateMappingChainProvider } from './generate_mapping_chain'; import { FilterBarLibMapMatchAllProvider } from './map_match_all'; diff --git a/src/ui/public/filter_bar/lib/map_flatten_and_wrap_filters.js b/src/ui/public/filter_bar/lib/map_flatten_and_wrap_filters.js index 6f1a9b877abb34..1c327d28a6b83f 100644 --- a/src/ui/public/filter_bar/lib/map_flatten_and_wrap_filters.js +++ b/src/ui/public/filter_bar/lib/map_flatten_and_wrap_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { FilterBarLibMapAndFlattenFiltersProvider } from './map_and_flatten_filters'; diff --git a/src/ui/public/filter_bar/lib/map_geo_bounding_box.js b/src/ui/public/filter_bar/lib/map_geo_bounding_box.js index 1e986737d9686f..b7011dcfac930f 100644 --- a/src/ui/public/filter_bar/lib/map_geo_bounding_box.js +++ b/src/ui/public/filter_bar/lib/map_geo_bounding_box.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { SavedObjectNotFound } from '../../errors'; diff --git a/src/ui/public/filter_bar/lib/map_geo_polygon.js b/src/ui/public/filter_bar/lib/map_geo_polygon.js index 2f40c73a4be236..20153af963789e 100644 --- a/src/ui/public/filter_bar/lib/map_geo_polygon.js +++ b/src/ui/public/filter_bar/lib/map_geo_polygon.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { SavedObjectNotFound } from '../../errors'; diff --git a/src/ui/public/filter_bar/lib/map_match_all.js b/src/ui/public/filter_bar/lib/map_match_all.js index 2d509816f9b3f4..deabe382758e44 100644 --- a/src/ui/public/filter_bar/lib/map_match_all.js +++ b/src/ui/public/filter_bar/lib/map_match_all.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function FilterBarLibMapMatchAllProvider(Promise) { return function (filter) { if (filter.match_all) { diff --git a/src/ui/public/filter_bar/lib/map_missing.js b/src/ui/public/filter_bar/lib/map_missing.js index 6a20dbae5bf714..a737671d0dd4f7 100644 --- a/src/ui/public/filter_bar/lib/map_missing.js +++ b/src/ui/public/filter_bar/lib/map_missing.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function FilterBarLibMapMissingProvider(Promise) { return function (filter) { if (filter.missing) { diff --git a/src/ui/public/filter_bar/lib/map_phrase.js b/src/ui/public/filter_bar/lib/map_phrase.js index 7e859fa5924dac..5d5036a96ca2fd 100644 --- a/src/ui/public/filter_bar/lib/map_phrase.js +++ b/src/ui/public/filter_bar/lib/map_phrase.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { SavedObjectNotFound } from '../../errors'; diff --git a/src/ui/public/filter_bar/lib/map_phrases.js b/src/ui/public/filter_bar/lib/map_phrases.js index 187ab7171aa765..eb6209e252b6f0 100644 --- a/src/ui/public/filter_bar/lib/map_phrases.js +++ b/src/ui/public/filter_bar/lib/map_phrases.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function FilterBarLibMapPhrasesProvider(Promise) { return function (filter) { const { type, key, value, params } = filter.meta; diff --git a/src/ui/public/filter_bar/lib/map_query_string.js b/src/ui/public/filter_bar/lib/map_query_string.js index b10231140d9f24..dec26bde5d4c74 100644 --- a/src/ui/public/filter_bar/lib/map_query_string.js +++ b/src/ui/public/filter_bar/lib/map_query_string.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function FilterBarLibMapQueryStringProvider(Promise) { return function (filter) { if (filter.query && filter.query.query_string) { diff --git a/src/ui/public/filter_bar/lib/map_range.js b/src/ui/public/filter_bar/lib/map_range.js index 1abe3dce39be12..c88874020c232c 100644 --- a/src/ui/public/filter_bar/lib/map_range.js +++ b/src/ui/public/filter_bar/lib/map_range.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { has, get } from 'lodash'; import { SavedObjectNotFound } from '../../errors'; diff --git a/src/ui/public/filter_bar/lib/only_disabled.js b/src/ui/public/filter_bar/lib/only_disabled.js index 3f8fad8be8b305..b78fde4e282093 100644 --- a/src/ui/public/filter_bar/lib/only_disabled.js +++ b/src/ui/public/filter_bar/lib/only_disabled.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; const pluckDisabled = function (filter) { diff --git a/src/ui/public/filter_bar/lib/only_state_changed.js b/src/ui/public/filter_bar/lib/only_state_changed.js index 9660eb412d4ccf..73e35bfec07eaa 100644 --- a/src/ui/public/filter_bar/lib/only_state_changed.js +++ b/src/ui/public/filter_bar/lib/only_state_changed.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { compareFilters } from './compare_filters'; const compareOptions = { disabled: true, negate: true }; diff --git a/src/ui/public/filter_bar/lib/uniq_filters.js b/src/ui/public/filter_bar/lib/uniq_filters.js index f5f68dedb336b1..f8e6d350f8dd93 100644 --- a/src/ui/public/filter_bar/lib/uniq_filters.js +++ b/src/ui/public/filter_bar/lib/uniq_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { dedupFilters } from './dedup_filters'; diff --git a/src/ui/public/filter_bar/push_filter.js b/src/ui/public/filter_bar/push_filter.js index 1f8c71da653bdc..265d9c47850645 100644 --- a/src/ui/public/filter_bar/push_filter.js +++ b/src/ui/public/filter_bar/push_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function FilterBarPushFilterProvider() { diff --git a/src/ui/public/filter_bar/query_filter.js b/src/ui/public/filter_bar/query_filter.js index 57600d3a8f77aa..4562796e508c5a 100644 --- a/src/ui/public/filter_bar/query_filter.js +++ b/src/ui/public/filter_bar/query_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { onlyDisabled } from './lib/only_disabled'; import { onlyStateChanged } from './lib/only_state_changed'; diff --git a/src/ui/public/filter_editor/filter_editor.html b/src/ui/public/filter_editor/filter_editor.html index 438347a4cce8b3..0b69a1d5661d8a 100644 --- a/src/ui/public/filter_editor/filter_editor.html +++ b/src/ui/public/filter_editor/filter_editor.html @@ -7,6 +7,7 @@
+
+
+
+
+
+
+ + Children + + + within the editor group + +
+
+
+
+
+`; + +exports[` renders as expected with actions 1`] = ` +
+
+
+
+ +
+
+ +
+
+
+
+
+
+ + Some children + +
+
+
+
+
+`; + +exports[` renders as expected with initial collapsed 1`] = ` +
+
+
+
+ +
+
+
+
+
+
+ + Children + + + within the editor group + +
+
+
+
+
+`; diff --git a/src/ui/public/vis/editors/components/editor_options_group.js b/src/ui/public/vis/editors/components/editor_options_group.js new file mode 100644 index 00000000000000..910d3e0cf0e8ff --- /dev/null +++ b/src/ui/public/vis/editors/components/editor_options_group.js @@ -0,0 +1,81 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import PropTypes from 'prop-types'; + +import './editor_options_group.less'; + +import { + EuiAccordion, + EuiPanel, + EuiSpacer, + EuiTitle, + htmlIdGenerator, +} from '@elastic/eui'; + + +/** + * A component to group different options in an editor together and give them + * a title. Should be used for all visualize editors when grouping options, + * to produce an aligned look and feel. + */ +function EditorOptionsGroup(props) { + return ( + + +

{props.title}

+ + } + > + + { props.children } +
+
+ ); +} + +EditorOptionsGroup.propTypes = { + /** + * The title of this options group, which will be shown with the group. + */ + title: PropTypes.string.isRequired, + /** + * Add additional elements as actions to the group. + */ + actions: PropTypes.node, + /** + * Whether the panel should be collapsed by default. + */ + initialIsCollapsed: PropTypes.bool, + /** + * All elements that should be within this group. + */ + children: PropTypes.node.isRequired, +}; + +export { EditorOptionsGroup }; diff --git a/src/ui/public/vis/editors/components/editor_options_group.less b/src/ui/public/vis/editors/components/editor_options_group.less new file mode 100644 index 00000000000000..e47fba05c3132e --- /dev/null +++ b/src/ui/public/vis/editors/components/editor_options_group.less @@ -0,0 +1,3 @@ +.editorOptionsGroup__panel + .editorOptionsGroup__panel { + margin-top: 8px; +} diff --git a/src/ui/public/vis/editors/components/editor_options_group.test.js b/src/ui/public/vis/editors/components/editor_options_group.test.js new file mode 100644 index 00000000000000..2f1ee6a303f877 --- /dev/null +++ b/src/ui/public/vis/editors/components/editor_options_group.test.js @@ -0,0 +1,71 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { render } from 'enzyme'; + +import 'test_utils/static_html_id_generator'; + +import { EuiButtonIcon } from '@elastic/eui'; +import { EditorOptionsGroup } from './editor_options_group'; + +describe('', () => { + it('renders as expected', () => { + const group = render( + + Children + within the editor group + + ); + expect(group).toMatchSnapshot(); + }); + + it('renders as expected with actions', () => { + const group = render( + + } + > + Some children + + ); + expect(group).toMatchSnapshot(); + }); + + it('renders as expected with initial collapsed', () => { + const group = render( + + Children + within the editor group + + ); + expect(group).toMatchSnapshot(); + }); +}); diff --git a/src/ui/public/vis/editors/components/index.js b/src/ui/public/vis/editors/components/index.js new file mode 100644 index 00000000000000..23e1cfbd2767d7 --- /dev/null +++ b/src/ui/public/vis/editors/components/index.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { EditorOptionsGroup } from './editor_options_group'; diff --git a/src/ui/public/vis/editors/default/__tests__/agg.js b/src/ui/public/vis/editors/default/__tests__/agg.js index 3309376423964f..6fc586417b075d 100644 --- a/src/ui/public/vis/editors/default/__tests__/agg.js +++ b/src/ui/public/vis/editors/default/__tests__/agg.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import _ from 'lodash'; diff --git a/src/ui/public/vis/editors/default/__tests__/agg_params.js b/src/ui/public/vis/editors/default/__tests__/agg_params.js index a217459b1f6a0f..3497db7cec6bea 100644 --- a/src/ui/public/vis/editors/default/__tests__/agg_params.js +++ b/src/ui/public/vis/editors/default/__tests__/agg_params.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import _ from 'lodash'; diff --git a/src/ui/public/vis/editors/default/__tests__/keyboard_move.js b/src/ui/public/vis/editors/default/__tests__/keyboard_move.js index d5a7c74718fa6b..6daf8a8d41ec04 100644 --- a/src/ui/public/vis/editors/default/__tests__/keyboard_move.js +++ b/src/ui/public/vis/editors/default/__tests__/keyboard_move.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vis/editors/default/__tests__/nesting_indicator.js b/src/ui/public/vis/editors/default/__tests__/nesting_indicator.js index 4508c1bbb14b68..79c3a22b38ae88 100644 --- a/src/ui/public/vis/editors/default/__tests__/nesting_indicator.js +++ b/src/ui/public/vis/editors/default/__tests__/nesting_indicator.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vis/editors/default/agg.html b/src/ui/public/vis/editors/default/agg.html index 5f68d534ed2160..0d2970076be47b 100644 --- a/src/ui/public/vis/editors/default/agg.html +++ b/src/ui/public/vis/editors/default/agg.html @@ -37,6 +37,7 @@ aria-label="Disable aggregation" tooltip="Disable aggregation" tooltip-append-to-body="true" + data-test-subj="disableAggregationBtn" type="button" class="kuiButton kuiButton--basic kuiButton--small"> diff --git a/src/ui/public/vis/editors/default/agg.js b/src/ui/public/vis/editors/default/agg.js index 954a8679fc1101..93dee5124783c6 100644 --- a/src/ui/public/vis/editors/default/agg.js +++ b/src/ui/public/vis/editors/default/agg.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './agg_params'; import './agg_add'; import { Direction } from './keyboard_move'; diff --git a/src/ui/public/vis/editors/default/agg_add.js b/src/ui/public/vis/editors/default/agg_add.js index 97ffea6f220069..3b160bfda86811 100644 --- a/src/ui/public/vis/editors/default/agg_add.js +++ b/src/ui/public/vis/editors/default/agg_add.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { AggConfig } from '../../agg_config'; import { uiModules } from '../../../modules'; import aggAddTemplate from './agg_add.html'; diff --git a/src/ui/public/vis/editors/default/agg_group.html b/src/ui/public/vis/editors/default/agg_group.html index 32b124a8255bcb..dfa04e4de9dc55 100644 --- a/src/ui/public/vis/editors/default/agg_group.html +++ b/src/ui/public/vis/editors/default/agg_group.html @@ -5,7 +5,7 @@
-
+
diff --git a/src/ui/public/vis/editors/default/agg_group.js b/src/ui/public/vis/editors/default/agg_group.js index dc142a22a3c2a1..6c0824cda4e2ec 100644 --- a/src/ui/public/vis/editors/default/agg_group.js +++ b/src/ui/public/vis/editors/default/agg_group.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import './agg'; import './agg_add'; diff --git a/src/ui/public/vis/editors/default/agg_param.js b/src/ui/public/vis/editors/default/agg_param.js index 2d0fa5222dc2b9..36e3d8c680fdd7 100644 --- a/src/ui/public/vis/editors/default/agg_param.js +++ b/src/ui/public/vis/editors/default/agg_param.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { uiModules } from '../../../modules'; diff --git a/src/ui/public/vis/editors/default/agg_params.js b/src/ui/public/vis/editors/default/agg_params.js index 643158d307a517..9a8660ae5be304 100644 --- a/src/ui/public/vis/editors/default/agg_params.js +++ b/src/ui/public/vis/editors/default/agg_params.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import _ from 'lodash'; import aggSelectHtml from './agg_select.html'; diff --git a/src/ui/public/vis/editors/default/default.js b/src/ui/public/vis/editors/default/default.js index 3d555d50ab243f..37d3d6d9e02181 100644 --- a/src/ui/public/vis/editors/default/default.js +++ b/src/ui/public/vis/editors/default/default.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './sidebar'; import './vis_options'; import './vis_editor_resizer'; diff --git a/src/ui/public/vis/editors/default/keyboard_move.js b/src/ui/public/vis/editors/default/keyboard_move.js index 4c69a249d34b6b..9f5b1eefa0ceb4 100644 --- a/src/ui/public/vis/editors/default/keyboard_move.js +++ b/src/ui/public/vis/editors/default/keyboard_move.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * The keyboardMove directive can be attached to elements, that can receive keydown events. * It will call the passed callback function and pass the direction in which an diff --git a/src/ui/public/vis/editors/default/nesting_indicator.js b/src/ui/public/vis/editors/default/nesting_indicator.js index 1914a03f94c478..930565dd645d7a 100644 --- a/src/ui/public/vis/editors/default/nesting_indicator.js +++ b/src/ui/public/vis/editors/default/nesting_indicator.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import { createColorPalette } from '../../components/color/color_palette'; import { uiModules } from '../../../modules'; diff --git a/src/ui/public/vis/editors/default/schemas.js b/src/ui/public/vis/editors/default/schemas.js index b9127dcef5fbae..e6f886dc6d07dc 100644 --- a/src/ui/public/vis/editors/default/schemas.js +++ b/src/ui/public/vis/editors/default/schemas.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { IndexedArray } from '../../../indexed_array'; import { AggParams } from '../../../agg_types/agg_params'; diff --git a/src/ui/public/vis/editors/default/sidebar.js b/src/ui/public/vis/editors/default/sidebar.js index a501db5d19f299..6503a11b998f13 100644 --- a/src/ui/public/vis/editors/default/sidebar.js +++ b/src/ui/public/vis/editors/default/sidebar.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import './agg_group'; import './vis_options'; diff --git a/src/ui/public/vis/editors/default/vis_editor_resizer.js b/src/ui/public/vis/editors/default/vis_editor_resizer.js index eed555f43fedd9..f2d0d364f6ef78 100644 --- a/src/ui/public/vis/editors/default/vis_editor_resizer.js +++ b/src/ui/public/vis/editors/default/vis_editor_resizer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import { uiModules } from '../../../modules'; import { keyCodes } from '@elastic/eui'; diff --git a/src/ui/public/vis/editors/default/vis_options.js b/src/ui/public/vis/editors/default/vis_options.js index 2a11997031d2de..68ed062bbfcc64 100644 --- a/src/ui/public/vis/editors/default/vis_options.js +++ b/src/ui/public/vis/editors/default/vis_options.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; diff --git a/src/ui/public/vis/editors/index.js b/src/ui/public/vis/editors/index.js new file mode 100644 index 00000000000000..d3ba8dd045781b --- /dev/null +++ b/src/ui/public/vis/editors/index.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { EditorOptionsGroup } from './components'; diff --git a/src/ui/public/vis/index.js b/src/ui/public/vis/index.js index fa80f5cb3a4118..711b465a1e8a53 100644 --- a/src/ui/public/vis/index.js +++ b/src/ui/public/vis/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { VisProvider } from './vis'; diff --git a/src/ui/public/vis/lib/calculate_object_hash.js b/src/ui/public/vis/lib/calculate_object_hash.js index beca5c6bd4e299..b119db8ba4f3be 100644 --- a/src/ui/public/vis/lib/calculate_object_hash.js +++ b/src/ui/public/vis/lib/calculate_object_hash.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // adopted form https://github.com/bevacqua/hash-sum function pad(hash, len) { diff --git a/src/ui/public/vis/lib/timezone.js b/src/ui/public/vis/lib/timezone.js index 38094cf499217a..473be70aa791df 100644 --- a/src/ui/public/vis/lib/timezone.js +++ b/src/ui/public/vis/lib/timezone.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const tzDetect = require('jstimezonedetect').jstz; import moment from 'moment'; diff --git a/src/ui/public/vis/map/color_util.js b/src/ui/public/vis/map/color_util.js new file mode 100644 index 00000000000000..c00f9c6acd917b --- /dev/null +++ b/src/ui/public/vis/map/color_util.js @@ -0,0 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export function getLegendColors(colorRamp) { + const colors = []; + colors[0] = getColor(colorRamp, 0); + colors[1] = getColor(colorRamp, Math.floor(colorRamp.length * 1 / 4)); + colors[2] = getColor(colorRamp, Math.floor(colorRamp.length * 2 / 4)); + colors[3] = getColor(colorRamp, Math.floor(colorRamp.length * 3 / 4)); + colors[4] = getColor(colorRamp, colorRamp.length - 1); + return colors; +} + +export function getColor(colorRamp, i) { + const color = colorRamp[i][1]; + const red = Math.floor(color[0] * 255); + const green = Math.floor(color[1] * 255); + const blue = Math.floor(color[2] * 255); + return `rgb(${red},${green},${blue})`; +} diff --git a/src/ui/public/vis/map/convert_to_geojson.js b/src/ui/public/vis/map/convert_to_geojson.js index ffccdec0e8bbfe..317c2b4a5865c5 100644 --- a/src/ui/public/vis/map/convert_to_geojson.js +++ b/src/ui/public/vis/map/convert_to_geojson.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { decodeGeoHash } from 'ui/utils/decode_geo_hash'; import { gridDimensions } from './grid_dimensions'; diff --git a/src/ui/public/vis/map/grid_dimensions.js b/src/ui/public/vis/map/grid_dimensions.js index d6a78768420f24..d608407f37c5a9 100644 --- a/src/ui/public/vis/map/grid_dimensions.js +++ b/src/ui/public/vis/map/grid_dimensions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; // geohash precision mapping of geohash grid cell dimensions (width x height, in meters) at equator. diff --git a/src/ui/public/vis/map/kibana_map.js b/src/ui/public/vis/map/kibana_map.js index 56c9ebe254f27d..a01bf26144e325 100644 --- a/src/ui/public/vis/map/kibana_map.js +++ b/src/ui/public/vis/map/kibana_map.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { EventEmitter } from 'events'; import L from 'leaflet'; import $ from 'jquery'; @@ -353,48 +372,11 @@ export class KibanaMap extends EventEmitter { return _.min([distanceX, distanceY]); } - getBounds() { - - const bounds = this._leafletMap.getBounds(); - if (!bounds) { - return null; - } - - const southEast = bounds.getSouthEast(); - const northWest = bounds.getNorthWest(); - let southEastLng = southEast.lng; - if (southEastLng > 180) { - southEastLng -= 360; - } - let northWestLng = northWest.lng; - if (northWestLng < -180) { - northWestLng += 360; - } - - const southEastLat = southEast.lat; - const northWestLat = northWest.lat; - - //Bounds cannot be created unless they form a box with larger than 0 dimensions - //Invalid areas are rejected by ES. - if (southEastLat === northWestLat || southEastLng === northWestLng) { - return; - } - - return { - bottom_right: { - lat: southEastLat, - lon: southEastLng - }, - top_left: { - lat: northWestLat, - lon: northWestLng - } - }; - } - _getLeafletBounds(resizeOnFail) { - const bounds = this._leafletMap.getBounds(); + const boundsRaw = this._leafletMap.getBounds(); + const bounds = this._leafletMap.wrapLatLngBounds(boundsRaw); + if (!bounds) { return null; } @@ -416,7 +398,8 @@ export class KibanaMap extends EventEmitter { } } - getUntrimmedBounds() { + getBounds() { + const bounds = this._getLeafletBounds(true); if (!bounds) { return null; @@ -664,14 +647,14 @@ export class KibanaMap extends EventEmitter { if (!centerFromUIState || centerFromMap.lon !== centerFromUIState[1] || centerFromMap.lat !== centerFromUIState[0]) { visualization.uiStateVal('mapCenter', [centerFromMap.lat, centerFromMap.lon]); } - visualization.sessionState.mapBounds = this.getUntrimmedBounds(); + visualization.sessionState.mapBounds = this.getBounds(); } this._leafletMap.on('resize', () => { - visualization.sessionState.mapBounds = this.getUntrimmedBounds(); + visualization.sessionState.mapBounds = this.getBounds(); }); this._leafletMap.on('load', () => { - visualization.sessionState.mapBounds = this.getUntrimmedBounds(); + visualization.sessionState.mapBounds = this.getBounds(); }); this.on('dragend', persistMapStateInUiState); this.on('zoomend', persistMapStateInUiState); diff --git a/src/ui/public/vis/map/kibana_map_layer.js b/src/ui/public/vis/map/kibana_map_layer.js index 6eba5b18129bf7..c1640d6b00f4d3 100644 --- a/src/ui/public/vis/map/kibana_map_layer.js +++ b/src/ui/public/vis/map/kibana_map_layer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { EventEmitter } from 'events'; diff --git a/src/ui/public/vis/map/service_settings.js b/src/ui/public/vis/map/service_settings.js index dc1244d03add6a..36c986f3ae4f5c 100644 --- a/src/ui/public/vis/map/service_settings.js +++ b/src/ui/public/vis/map/service_settings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiModules } from '../../modules'; import _ from 'lodash'; import MarkdownIt from 'markdown-it'; diff --git a/src/ui/public/vis/request_handlers/courier.js b/src/ui/public/vis/request_handlers/courier.js index 36a9c33c4050f4..85835cbd22b930 100644 --- a/src/ui/public/vis/request_handlers/courier.js +++ b/src/ui/public/vis/request_handlers/courier.js @@ -1,6 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { SearchSourceProvider } from '../../courier/data_source/search_source'; import { VisRequestHandlersRegistryProvider } from '../../registry/vis_request_handlers'; +import { calculateObjectHash } from '../lib/calculate_object_hash'; const CourierRequestHandlerProvider = function (Private, courier, timefilter) { const SearchSource = Private(SearchSourceProvider); @@ -8,37 +28,18 @@ const CourierRequestHandlerProvider = function (Private, courier, timefilter) { /** * TODO: This code can be removed as soon as we got rid of inheritance in the * searchsource and pass down every filter explicitly. - * we're only adding one range filter against the timeFieldName to ensure - * that our filter is the only one applied and override the global filters. - * this does rely on the "implementation detail" that filters are added first - * on the leaf SearchSource and subsequently on the parents. + * We are filtering out the global timefilter by the meta key set by the root + * search source on that filter. */ function removeSearchSourceParentTimefilter(searchSource) { - searchSource.addFilterPredicate((filter, state) => { - if (!filter.range) { - return true; - } - - const index = searchSource.index() || searchSource.getParent().index(); - const timeFieldName = index && index.timeFieldName; - if (!index || !timeFieldName) { - return true; - } - - // Only check if we need to filter out this filter if it's actual a range filter - // on our time field and not any other field. - if (!filter.range[timeFieldName]) { - return true; - } - - return !(state.filters || []).find(f => f.range && f.range[timeFieldName]); + searchSource.addFilterPredicate((filter) => { + return !_.get(filter, 'meta._globalTimefilter', false); }); - } return { name: 'courier', - handler: function (vis, { appState, queryFilter, searchSource, timeRange }) { + handler: function (vis, { appState, queryFilter, searchSource, timeRange, forceFetch }) { // Create a new search source that inherits the original search source // but has the propriate timeRange applied via a filter. @@ -60,6 +61,14 @@ const CourierRequestHandlerProvider = function (Private, courier, timefilter) { } }); + requestSearchSource.aggs(function () { + return vis.getAggConfig().toDsl(); + }); + + requestSearchSource.onRequestStart((searchSource, searchRequest) => { + return vis.onSearchRequestStart(searchSource, searchRequest); + }); + // Add the explicit passed timeRange as a filter to the requestSearchSource. requestSearchSource.filter(() => { return timefilter.get(searchSource.index(), timeRange); @@ -72,22 +81,11 @@ const CourierRequestHandlerProvider = function (Private, courier, timefilter) { searchSource.set('query', appState.query); } - // AggConfig contains circular reference to vis, which contains visualization parameters, - // which we should not look at - const copyAggs = (aggs) => { - return aggs.map(agg => { - return { - type: agg.type, - params: agg.params - }; - }); - }; - const shouldQuery = () => { - if (!searchSource.lastQuery || vis.reload) return true; + if (!searchSource.lastQuery || forceFetch) return true; if (!_.isEqual(_.cloneDeep(searchSource.get('filter')), searchSource.lastQuery.filter)) return true; if (!_.isEqual(_.cloneDeep(searchSource.get('query')), searchSource.lastQuery.query)) return true; - if (!_.isEqual(_.cloneDeep(copyAggs(vis.aggs)), searchSource.lastQuery.aggs)) return true; + if (!_.isEqual(calculateObjectHash(vis.getAggConfig()), searchSource.lastQuery.aggs)) return true; if (!_.isEqual(_.cloneDeep(timeRange), searchSource.lastQuery.timeRange)) return true; return false; @@ -95,12 +93,11 @@ const CourierRequestHandlerProvider = function (Private, courier, timefilter) { return new Promise((resolve, reject) => { if (shouldQuery()) { - delete vis.reload; requestSearchSource.onResults().then(resp => { searchSource.lastQuery = { filter: _.cloneDeep(searchSource.get('filter')), query: _.cloneDeep(searchSource.get('query')), - aggs: _.cloneDeep(copyAggs(vis.aggs)), + aggs: calculateObjectHash(vis.getAggConfig()), timeRange: _.cloneDeep(timeRange) }; diff --git a/src/ui/public/vis/request_handlers/none.js b/src/ui/public/vis/request_handlers/none.js index 27162eb4607b2e..61995f53eb5147 100644 --- a/src/ui/public/vis/request_handlers/none.js +++ b/src/ui/public/vis/request_handlers/none.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VisRequestHandlersRegistryProvider } from '../../registry/vis_request_handlers'; const noneRequestHandlerProvider = function () { diff --git a/src/ui/public/vis/response_handlers/basic.js b/src/ui/public/vis/response_handlers/basic.js index d7da88be406e16..f4a8663ed30e7b 100644 --- a/src/ui/public/vis/response_handlers/basic.js +++ b/src/ui/public/vis/response_handlers/basic.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { AggResponseIndexProvider } from '../../agg_response'; import { TabifyTable } from '../../agg_response/tabify/_table'; diff --git a/src/ui/public/vis/response_handlers/none.js b/src/ui/public/vis/response_handlers/none.js index 8601c2b8d9a133..9b60d2c59f26da 100644 --- a/src/ui/public/vis/response_handlers/none.js +++ b/src/ui/public/vis/response_handlers/none.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // response handler: // receives response data and vis configuration // returns a promise diff --git a/src/ui/public/vis/response_handlers/tabify.js b/src/ui/public/vis/response_handlers/tabify.js index b3e3d4fa74a457..a5d32be55ec719 100644 --- a/src/ui/public/vis/response_handlers/tabify.js +++ b/src/ui/public/vis/response_handlers/tabify.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { AggResponseIndexProvider } from '../../agg_response'; import { VisResponseHandlersRegistryProvider } from '../../registry/vis_response_handlers'; diff --git a/src/ui/public/vis/update_status.js b/src/ui/public/vis/update_status.js index fea0b9cbb92062..c216fab742d21b 100644 --- a/src/ui/public/vis/update_status.js +++ b/src/ui/public/vis/update_status.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { calculateObjectHash } from './lib/calculate_object_hash'; const Status = { diff --git a/src/ui/public/vis/update_status.test.js b/src/ui/public/vis/update_status.test.js index f993ddfae51371..0390f2c9ad1224 100644 --- a/src/ui/public/vis/update_status.test.js +++ b/src/ui/public/vis/update_status.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { getUpdateStatus, Status } from './update_status'; // Parts of the tests in this file are generated more dynamically, based on the diff --git a/src/ui/public/vis/vis.js b/src/ui/public/vis/vis.js index 959576e03c8dc5..e25608a17a276a 100644 --- a/src/ui/public/vis/vis.js +++ b/src/ui/public/vis/vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * @name Vis * @@ -11,7 +30,7 @@ import { EventEmitter } from 'events'; import _ from 'lodash'; import { VisTypesRegistryProvider } from '../registry/vis_types'; -import { VisAggConfigsProvider } from './agg_configs'; +import { AggConfigs } from './agg_configs'; import { PersistedState } from '../persisted_state'; import { UtilsBrushEventProvider } from '../utils/brush_event'; import { FilterBarQueryFilterProvider } from '../filter_bar/query_filter'; @@ -23,7 +42,6 @@ import { SavedObjectsClientProvider } from '../saved_objects'; export function VisProvider(Private, Promise, indexPatterns, timefilter, getAppState) { const visTypes = Private(VisTypesRegistryProvider); - const AggConfigs = Private(VisAggConfigsProvider); const brushEvent = Private(UtilsBrushEventProvider); const queryFilter = Private(FilterBarQueryFilterProvider); const filterBarClickHandler = Private(FilterBarClickHandlerProvider); diff --git a/src/ui/public/vis/vis_category.js b/src/ui/public/vis/vis_category.js index 273f222f81d1df..c2074f5ae248de 100644 --- a/src/ui/public/vis/vis_category.js +++ b/src/ui/public/vis/vis_category.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * You should always make sure that every CATEGORY on top have a corresponding * display name in the below object, otherwise they won't be shown properly diff --git a/src/ui/public/vis/vis_factory.js b/src/ui/public/vis/vis_factory.js index 398e0da89b1ad4..fe2265ae52a147 100644 --- a/src/ui/public/vis/vis_factory.js +++ b/src/ui/public/vis/vis_factory.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VisTypeProvider, AngularVisTypeProvider, ReactVisTypeProvider, VislibVisTypeProvider } from './vis_types'; export const VisFactoryProvider = (Private) => { diff --git a/src/ui/public/vis/vis_types/angular_vis_type.js b/src/ui/public/vis/vis_types/angular_vis_type.js index 285244182a5f1a..ac55b5e83b0d5b 100644 --- a/src/ui/public/vis/vis_types/angular_vis_type.js +++ b/src/ui/public/vis/vis_types/angular_vis_type.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VisTypeProvider } from './'; import $ from 'jquery'; diff --git a/src/ui/public/vis/vis_types/base_vis_type.js b/src/ui/public/vis/vis_types/base_vis_type.js index 718c4716864ed1..9291c645dd930c 100644 --- a/src/ui/public/vis/vis_types/base_vis_type.js +++ b/src/ui/public/vis/vis_types/base_vis_type.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { CATEGORY } from '../vis_category'; import _ from 'lodash'; diff --git a/src/ui/public/vis/vis_types/index.js b/src/ui/public/vis/vis_types/index.js index 6755b55428d41b..3f1ee436d13402 100644 --- a/src/ui/public/vis/vis_types/index.js +++ b/src/ui/public/vis/vis_types/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VisTypeProvider } from './base_vis_type'; import { AngularVisTypeProvider } from './angular_vis_type'; import { VislibVisTypeProvider } from './vislib_vis_type'; diff --git a/src/ui/public/vis/vis_types/react_vis_type.js b/src/ui/public/vis/vis_types/react_vis_type.js index 8bb6ade3067486..d6a7aebcd0934f 100644 --- a/src/ui/public/vis/vis_types/react_vis_type.js +++ b/src/ui/public/vis/vis_types/react_vis_type.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { VisTypeProvider } from './'; diff --git a/src/ui/public/vis/vis_types/vislib_vis_type.js b/src/ui/public/vis/vis_types/vislib_vis_type.js index ec834fd35f4260..93dcd3eaf1b61b 100644 --- a/src/ui/public/vis/vis_types/vislib_vis_type.js +++ b/src/ui/public/vis/vis_types/vislib_vis_type.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import 'plugins/kbn_vislib_vis_types/controls/vislib_basic_options'; import 'plugins/kbn_vislib_vis_types/controls/point_series_options'; import 'plugins/kbn_vislib_vis_types/controls/line_interpolation_option'; diff --git a/src/ui/public/vis/vis_update.js b/src/ui/public/vis/vis_update.js index 2b9ff1032e3c53..0a6c1f5e066276 100644 --- a/src/ui/public/vis/vis_update.js +++ b/src/ui/public/vis/vis_update.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // TODO: this should be moved to vis_update_state // Currently the migration takes place in Vis when calling setCurrentState. // It should rather convert the raw saved object before starting to instantiate diff --git a/src/ui/public/vis/vis_update_state.js b/src/ui/public/vis/vis_update_state.js index d009af3779d4cf..8f6be3a04d2fdd 100644 --- a/src/ui/public/vis/vis_update_state.js +++ b/src/ui/public/vis/vis_update_state.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; /** @@ -15,6 +34,21 @@ function convertHeatmapLabelColor(visState) { } } +/** + * Update old terms aggregation format to new terms aggregation format. This will + * update the following things: + * - Rewrite orderBy: _term to orderBy: _key (new API in Elasticsearch) + */ +function convertTermAggregation(visState) { + if (visState.aggs) { + visState.aggs.forEach(agg => { + if (agg.type === 'terms' && agg.params && agg.params.orderBy === '_term') { + agg.params.orderBy = '_key'; + } + }); + } +} + /** * This function is responsible for updating old visStates - the actual saved object * object - into the format, that will be required by the current Kibana version. @@ -26,6 +60,8 @@ export const updateOldState = (visState) => { if (!visState) return visState; const newState = _.cloneDeep(visState); + convertTermAggregation(newState); + if (visState.type === 'gauge' && visState.fontSize) { delete newState.fontSize; _.set(newState, 'gauge.style.fontSize', visState.fontSize); diff --git a/src/ui/public/vislib/__tests__/components/heatmap_color.js b/src/ui/public/vislib/__tests__/components/heatmap_color.js index 2a8b4654e69c58..7f00dc2d3ca0d8 100644 --- a/src/ui/public/vislib/__tests__/components/heatmap_color.js +++ b/src/ui/public/vislib/__tests__/components/heatmap_color.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import { getHeatmapColors } from '../../components/color/heatmap_color'; diff --git a/src/ui/public/vislib/__tests__/components/labels.js b/src/ui/public/vislib/__tests__/components/labels.js index 22f25298361add..e454bc1cf11b84 100644 --- a/src/ui/public/vislib/__tests__/components/labels.js +++ b/src/ui/public/vislib/__tests__/components/labels.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/components/zero_injection.js b/src/ui/public/vislib/__tests__/components/zero_injection.js index dfb3bd0f659e34..abadb47e74ad40 100644 --- a/src/ui/public/vislib/__tests__/components/zero_injection.js +++ b/src/ui/public/vislib/__tests__/components/zero_injection.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import expect from 'expect.js'; diff --git a/src/ui/public/vislib/__tests__/index.js b/src/ui/public/vislib/__tests__/index.js index d44eb7f6498798..dbdd17028aee7e 100644 --- a/src/ui/public/vislib/__tests__/index.js +++ b/src/ui/public/vislib/__tests__/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import expect from 'expect.js'; diff --git a/src/ui/public/vislib/__tests__/lib/axis/axis.js b/src/ui/public/vislib/__tests__/lib/axis/axis.js index 339b425d166198..0f5d2281bec58b 100644 --- a/src/ui/public/vislib/__tests__/lib/axis/axis.js +++ b/src/ui/public/vislib/__tests__/lib/axis/axis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/lib/axis_title.js b/src/ui/public/vislib/__tests__/lib/axis_title.js index ed7da9ce793eda..9bd9cc91537f07 100644 --- a/src/ui/public/vislib/__tests__/lib/axis_title.js +++ b/src/ui/public/vislib/__tests__/lib/axis_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; diff --git a/src/ui/public/vislib/__tests__/lib/chart_title.js b/src/ui/public/vislib/__tests__/lib/chart_title.js index f369a711089c49..5955c19a02fc40 100644 --- a/src/ui/public/vislib/__tests__/lib/chart_title.js +++ b/src/ui/public/vislib/__tests__/lib/chart_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/lib/data.js b/src/ui/public/vislib/__tests__/lib/data.js index c52ce2e79088fd..5afdd2241c7a16 100644 --- a/src/ui/public/vislib/__tests__/lib/data.js +++ b/src/ui/public/vislib/__tests__/lib/data.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/vislib/__tests__/lib/dispatch.js b/src/ui/public/vislib/__tests__/lib/dispatch.js index 86d60a8f412679..6b2b7b01845d55 100644 --- a/src/ui/public/vislib/__tests__/lib/dispatch.js +++ b/src/ui/public/vislib/__tests__/lib/dispatch.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import d3 from 'd3'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/lib/error_handler.js b/src/ui/public/vislib/__tests__/lib/error_handler.js index 0c06fe0b781c2f..804939001aa106 100644 --- a/src/ui/public/vislib/__tests__/lib/error_handler.js +++ b/src/ui/public/vislib/__tests__/lib/error_handler.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/lib/handler/handler.js b/src/ui/public/vislib/__tests__/lib/handler/handler.js index 6d27f73f81e857..518fc9595ab8d3 100644 --- a/src/ui/public/vislib/__tests__/lib/handler/handler.js +++ b/src/ui/public/vislib/__tests__/lib/handler/handler.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/vislib/__tests__/lib/layout/layout.js b/src/ui/public/vislib/__tests__/lib/layout/layout.js index 55f101a0dbd532..8406cf3bf03c90 100644 --- a/src/ui/public/vislib/__tests__/lib/layout/layout.js +++ b/src/ui/public/vislib/__tests__/lib/layout/layout.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/vislib/__tests__/lib/layout/layout_types.js b/src/ui/public/vislib/__tests__/lib/layout/layout_types.js index ead5c779f312a6..8d4c80f7283406 100644 --- a/src/ui/public/vislib/__tests__/lib/layout/layout_types.js +++ b/src/ui/public/vislib/__tests__/lib/layout/layout_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js b/src/ui/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js index 913f1b29a97510..4b8f242517ed36 100644 --- a/src/ui/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js +++ b/src/ui/public/vislib/__tests__/lib/layout/splits/column_chart/splits.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js b/src/ui/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js index 2b8d398ab936ff..cb849bc6bf601b 100644 --- a/src/ui/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js +++ b/src/ui/public/vislib/__tests__/lib/layout/splits/gauge_chart/splits.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/vislib/__tests__/lib/layout/types/column_layout.js b/src/ui/public/vislib/__tests__/lib/layout/types/column_layout.js index 0f7c0ca8e946eb..6086b7007af582 100644 --- a/src/ui/public/vislib/__tests__/lib/layout/types/column_layout.js +++ b/src/ui/public/vislib/__tests__/lib/layout/types/column_layout.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/lib/types/point_series.js b/src/ui/public/vislib/__tests__/lib/types/point_series.js index 177b70f96ca843..f5d8e16092e0b4 100644 --- a/src/ui/public/vislib/__tests__/lib/types/point_series.js +++ b/src/ui/public/vislib/__tests__/lib/types/point_series.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import ngMock from 'ng_mock'; import expect from 'expect.js'; import stackedSeries from 'fixtures/vislib/mock_data/date_histogram/_stacked_series'; diff --git a/src/ui/public/vislib/__tests__/lib/vis_config.js b/src/ui/public/vislib/__tests__/lib/vis_config.js index 1bf1397b0017fb..66f3651883e25e 100644 --- a/src/ui/public/vislib/__tests__/lib/vis_config.js +++ b/src/ui/public/vislib/__tests__/lib/vis_config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import ngMock from 'ng_mock'; import expect from 'expect.js'; diff --git a/src/ui/public/vislib/__tests__/lib/x_axis.js b/src/ui/public/vislib/__tests__/lib/x_axis.js index d401d3a770f940..183e1b7fc11639 100644 --- a/src/ui/public/vislib/__tests__/lib/x_axis.js +++ b/src/ui/public/vislib/__tests__/lib/x_axis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/lib/y_axis.js b/src/ui/public/vislib/__tests__/lib/y_axis.js index b115b0fef353f6..b59ba8e6e31588 100644 --- a/src/ui/public/vislib/__tests__/lib/y_axis.js +++ b/src/ui/public/vislib/__tests__/lib/y_axis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import d3 from 'd3'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/vis.js b/src/ui/public/vislib/__tests__/vis.js index 53e8ae5c2288a3..2875efda1a8fe2 100644 --- a/src/ui/public/vislib/__tests__/vis.js +++ b/src/ui/public/vislib/__tests__/vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/visualizations/area_chart.js b/src/ui/public/vislib/__tests__/visualizations/area_chart.js index 7a0b32023913e1..ac7944ae8dead6 100644 --- a/src/ui/public/vislib/__tests__/visualizations/area_chart.js +++ b/src/ui/public/vislib/__tests__/visualizations/area_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/visualizations/chart.js b/src/ui/public/vislib/__tests__/visualizations/chart.js index 1d7299f77a55ed..cf6dea67a09cf0 100644 --- a/src/ui/public/vislib/__tests__/visualizations/chart.js +++ b/src/ui/public/vislib/__tests__/visualizations/chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/visualizations/column_chart.js b/src/ui/public/vislib/__tests__/visualizations/column_chart.js index 27e7e8b6b2a278..8493ae9f53b641 100644 --- a/src/ui/public/vislib/__tests__/visualizations/column_chart.js +++ b/src/ui/public/vislib/__tests__/visualizations/column_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import _ from 'lodash'; diff --git a/src/ui/public/vislib/__tests__/visualizations/gauge_chart.js b/src/ui/public/vislib/__tests__/visualizations/gauge_chart.js index 243d9df02b9897..50fea1597eb107 100644 --- a/src/ui/public/vislib/__tests__/visualizations/gauge_chart.js +++ b/src/ui/public/vislib/__tests__/visualizations/gauge_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import $ from 'jquery'; diff --git a/src/ui/public/vislib/__tests__/visualizations/heatmap_chart.js b/src/ui/public/vislib/__tests__/visualizations/heatmap_chart.js index 02d2c19aca789d..8844bacb975e55 100644 --- a/src/ui/public/vislib/__tests__/visualizations/heatmap_chart.js +++ b/src/ui/public/vislib/__tests__/visualizations/heatmap_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import _ from 'lodash'; diff --git a/src/ui/public/vislib/__tests__/visualizations/line_chart.js b/src/ui/public/vislib/__tests__/visualizations/line_chart.js index 7aa989c702c263..064b422897445e 100644 --- a/src/ui/public/vislib/__tests__/visualizations/line_chart.js +++ b/src/ui/public/vislib/__tests__/visualizations/line_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/visualizations/pie_chart.js b/src/ui/public/vislib/__tests__/visualizations/pie_chart.js index c366f2b2c4e818..5d6fcd8090d811 100644 --- a/src/ui/public/vislib/__tests__/visualizations/pie_chart.js +++ b/src/ui/public/vislib/__tests__/visualizations/pie_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/visualizations/time_marker.js b/src/ui/public/vislib/__tests__/visualizations/time_marker.js index 547ac4f44503f0..c5d4cfb268ee16 100644 --- a/src/ui/public/vislib/__tests__/visualizations/time_marker.js +++ b/src/ui/public/vislib/__tests__/visualizations/time_marker.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/vislib/__tests__/visualizations/vis_types.js b/src/ui/public/vislib/__tests__/visualizations/vis_types.js index bdf60bcf15c4ae..f4621989ab7b2a 100644 --- a/src/ui/public/vislib/__tests__/visualizations/vis_types.js +++ b/src/ui/public/vislib/__tests__/visualizations/vis_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import ngMock from 'ng_mock'; import _ from 'lodash'; diff --git a/src/ui/public/vislib/components/color/colormaps.js b/src/ui/public/vislib/components/color/colormaps.js index cf848ac5e49299..d4198a42b8d3cb 100644 --- a/src/ui/public/vislib/components/color/colormaps.js +++ b/src/ui/public/vislib/components/color/colormaps.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const vislibColorMaps = []; // Sequential diff --git a/src/ui/public/vislib/components/color/heatmap_color.js b/src/ui/public/vislib/components/color/heatmap_color.js index 895ee4469a97e8..62d545b818fbed 100644 --- a/src/ui/public/vislib/components/color/heatmap_color.js +++ b/src/ui/public/vislib/components/color/heatmap_color.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { vislibColorMaps } from './colormaps'; diff --git a/src/ui/public/vislib/components/color/truncated_colormaps.js b/src/ui/public/vislib/components/color/truncated_colormaps.js index a2fda36727674a..32d304d7cae672 100644 --- a/src/ui/public/vislib/components/color/truncated_colormaps.js +++ b/src/ui/public/vislib/components/color/truncated_colormaps.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { vislibColorMaps } from './colormaps'; export const truncatedColorMaps = {}; diff --git a/src/ui/public/vislib/components/labels/data_array.js b/src/ui/public/vislib/components/labels/data_array.js index c94eaab58382a2..95792a9508b6f1 100644 --- a/src/ui/public/vislib/components/labels/data_array.js +++ b/src/ui/public/vislib/components/labels/data_array.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { VislibComponentsLabelsFlattenSeriesProvider } from './flatten_series'; diff --git a/src/ui/public/vislib/components/labels/flatten_series.js b/src/ui/public/vislib/components/labels/flatten_series.js index 482637d8950e9e..bd8494bb6ceb16 100644 --- a/src/ui/public/vislib/components/labels/flatten_series.js +++ b/src/ui/public/vislib/components/labels/flatten_series.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function VislibComponentsLabelsFlattenSeriesProvider() { diff --git a/src/ui/public/vislib/components/labels/index.js b/src/ui/public/vislib/components/labels/index.js index 77004990faffdc..e3c920fb6a601f 100644 --- a/src/ui/public/vislib/components/labels/index.js +++ b/src/ui/public/vislib/components/labels/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { VislibComponentsLabelsLabelsProvider } from './labels'; diff --git a/src/ui/public/vislib/components/labels/labels.js b/src/ui/public/vislib/components/labels/labels.js index 75ff489cc6d0d5..a4a2316bad0600 100644 --- a/src/ui/public/vislib/components/labels/labels.js +++ b/src/ui/public/vislib/components/labels/labels.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { VislibComponentsLabelsDataArrayProvider } from './data_array'; import { VislibComponentsLabelsUniqLabelsProvider } from './uniq_labels'; diff --git a/src/ui/public/vislib/components/labels/truncate_labels.js b/src/ui/public/vislib/components/labels/truncate_labels.js index 6dfe2ee3ec76ba..daf802b844327d 100644 --- a/src/ui/public/vislib/components/labels/truncate_labels.js +++ b/src/ui/public/vislib/components/labels/truncate_labels.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import d3 from 'd3'; diff --git a/src/ui/public/vislib/components/labels/uniq_labels.js b/src/ui/public/vislib/components/labels/uniq_labels.js index 9d96e4b2e1104c..2b95c875255004 100644 --- a/src/ui/public/vislib/components/labels/uniq_labels.js +++ b/src/ui/public/vislib/components/labels/uniq_labels.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function VislibComponentsLabelsUniqLabelsProvider() { diff --git a/src/ui/public/vislib/components/zero_injection/flatten_data.js b/src/ui/public/vislib/components/zero_injection/flatten_data.js index 347bfc4802367a..0689ec4f4c060d 100644 --- a/src/ui/public/vislib/components/zero_injection/flatten_data.js +++ b/src/ui/public/vislib/components/zero_injection/flatten_data.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function VislibComponentsZeroInjectionFlattenDataProvider() { diff --git a/src/ui/public/vislib/components/zero_injection/inject_zeros.js b/src/ui/public/vislib/components/zero_injection/inject_zeros.js index 307522e836a028..d74c4809bae7ae 100644 --- a/src/ui/public/vislib/components/zero_injection/inject_zeros.js +++ b/src/ui/public/vislib/components/zero_injection/inject_zeros.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VislibComponentsZeroInjectionOrderedXKeysProvider } from './ordered_x_keys'; import { VislibComponentsZeroInjectionZeroFilledArrayProvider } from './zero_filled_array'; import { VislibComponentsZeroInjectionZeroFillDataArrayProvider } from './zero_fill_data_array'; diff --git a/src/ui/public/vislib/components/zero_injection/ordered_x_keys.js b/src/ui/public/vislib/components/zero_injection/ordered_x_keys.js index 3c27f6e3960940..6b03d72e7ec2f3 100644 --- a/src/ui/public/vislib/components/zero_injection/ordered_x_keys.js +++ b/src/ui/public/vislib/components/zero_injection/ordered_x_keys.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import moment from 'moment'; import { VislibComponentsZeroInjectionUniqKeysProvider } from './uniq_keys'; diff --git a/src/ui/public/vislib/components/zero_injection/uniq_keys.js b/src/ui/public/vislib/components/zero_injection/uniq_keys.js index 719a2461cf3bfe..fa2a3c0cf2ac00 100644 --- a/src/ui/public/vislib/components/zero_injection/uniq_keys.js +++ b/src/ui/public/vislib/components/zero_injection/uniq_keys.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { VislibComponentsZeroInjectionFlattenDataProvider } from './flatten_data'; diff --git a/src/ui/public/vislib/components/zero_injection/zero_fill_data_array.js b/src/ui/public/vislib/components/zero_injection/zero_fill_data_array.js index a425c663fddd36..e543dd14e53535 100644 --- a/src/ui/public/vislib/components/zero_injection/zero_fill_data_array.js +++ b/src/ui/public/vislib/components/zero_injection/zero_fill_data_array.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function VislibComponentsZeroInjectionZeroFillDataArrayProvider() { diff --git a/src/ui/public/vislib/components/zero_injection/zero_filled_array.js b/src/ui/public/vislib/components/zero_injection/zero_filled_array.js index 3df49ed982ae34..106e2985fe5e4d 100644 --- a/src/ui/public/vislib/components/zero_injection/zero_filled_array.js +++ b/src/ui/public/vislib/components/zero_injection/zero_filled_array.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function VislibComponentsZeroInjectionZeroFilledArrayProvider() { /* * Accepts an array of x axis values (strings or numbers). diff --git a/src/ui/public/vislib/index.js b/src/ui/public/vislib/index.js index 059045a317e84c..0d527d08a28a06 100644 --- a/src/ui/public/vislib/index.js +++ b/src/ui/public/vislib/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VislibProvider } from './vislib'; // eslint-disable-next-line @elastic/kibana-custom/no-default-export diff --git a/src/ui/public/vislib/lib/_data_label.js b/src/ui/public/vislib/lib/_data_label.js index 56b8978efb2370..f7c5fc95615770 100644 --- a/src/ui/public/vislib/lib/_data_label.js +++ b/src/ui/public/vislib/lib/_data_label.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; /** * Creates a string based on the hex color passed in diff --git a/src/ui/public/vislib/lib/_error_handler.js b/src/ui/public/vislib/lib/_error_handler.js index c2975e249a0e5f..66ad40829e6ce5 100644 --- a/src/ui/public/vislib/lib/_error_handler.js +++ b/src/ui/public/vislib/lib/_error_handler.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { ContainerTooSmall } from '../../errors'; diff --git a/src/ui/public/vislib/lib/alerts.js b/src/ui/public/vislib/lib/alerts.js index 7b9b8931831855..9ad08467e0fefd 100644 --- a/src/ui/public/vislib/lib/alerts.js +++ b/src/ui/public/vislib/lib/alerts.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import _ from 'lodash'; diff --git a/src/ui/public/vislib/lib/axis/axis.js b/src/ui/public/vislib/lib/axis/axis.js index eb322dc177ad9d..a2e61a1803c6b4 100644 --- a/src/ui/public/vislib/lib/axis/axis.js +++ b/src/ui/public/vislib/lib/axis/axis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; diff --git a/src/ui/public/vislib/lib/axis/axis_config.js b/src/ui/public/vislib/lib/axis/axis_config.js index 5a904c328abddc..bc516381c1dbb2 100644 --- a/src/ui/public/vislib/lib/axis/axis_config.js +++ b/src/ui/public/vislib/lib/axis/axis_config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import d3 from 'd3'; import { SCALE_MODES } from './scale_modes'; diff --git a/src/ui/public/vislib/lib/axis/axis_labels.js b/src/ui/public/vislib/lib/axis/axis_labels.js index d6143f5439996d..376e92fd53b402 100644 --- a/src/ui/public/vislib/lib/axis/axis_labels.js +++ b/src/ui/public/vislib/lib/axis/axis_labels.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import $ from 'jquery'; import { truncateLabel } from '../../components/labels/truncate_labels'; @@ -77,12 +96,17 @@ export function VislibAxisLabelsProvider() { return function (selection) { if (!config.get('labels.filter')) return; + + const el = $(config.get('rootEl')).find(config.get('elSelector')); + const maxSize = config.isHorizontal() ? el.width() : el.height(); + const scaleRange = self.axisScale.scale.range(); + const scaleWidth = scaleRange[scaleRange.length - 1] - scaleRange[0]; + const scaleStartPad = .5 * (maxSize - scaleWidth); + selection.selectAll('.tick text') .text(function (d) { const par = d3.select(this.parentNode).node(); - const el = $(config.get('rootEl')).find(config.get('elSelector')); - const maxSize = config.isHorizontal() ? el.width() : el.height(); - const myPos = config.isHorizontal() ? self.axisScale.scale(d) : maxSize - self.axisScale.scale(d); + const myPos = scaleStartPad + (config.isHorizontal() ? self.axisScale.scale(d) : maxSize - self.axisScale.scale(d)); const mySize = (config.isHorizontal() ? par.getBBox().width : par.getBBox().height) * padding; const halfSize = mySize / 2; diff --git a/src/ui/public/vislib/lib/axis/axis_scale.js b/src/ui/public/vislib/lib/axis/axis_scale.js index 008e295c0d05c4..20a2ea41c564dc 100644 --- a/src/ui/public/vislib/lib/axis/axis_scale.js +++ b/src/ui/public/vislib/lib/axis/axis_scale.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import moment from 'moment'; diff --git a/src/ui/public/vislib/lib/axis/axis_title.js b/src/ui/public/vislib/lib/axis/axis_title.js index 4df2a37f377964..e66f2c5f89a3d7 100644 --- a/src/ui/public/vislib/lib/axis/axis_title.js +++ b/src/ui/public/vislib/lib/axis/axis_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import $ from 'jquery'; diff --git a/src/ui/public/vislib/lib/axis/index.js b/src/ui/public/vislib/lib/axis/index.js index 6f54619b6144e7..8116f4bcdd1653 100644 --- a/src/ui/public/vislib/lib/axis/index.js +++ b/src/ui/public/vislib/lib/axis/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { VislibLibAxisProvider } from './axis'; diff --git a/src/ui/public/vislib/lib/axis/scale_modes.js b/src/ui/public/vislib/lib/axis/scale_modes.js index ac18223c97da1c..7c42fbc4d6e7d0 100644 --- a/src/ui/public/vislib/lib/axis/scale_modes.js +++ b/src/ui/public/vislib/lib/axis/scale_modes.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const SCALE_MODES = { NORMAL: 'normal', PERCENTAGE: 'percentage', diff --git a/src/ui/public/vislib/lib/chart_grid.js b/src/ui/public/vislib/lib/chart_grid.js index c434662f55306f..20ecbe2673c4d2 100644 --- a/src/ui/public/vislib/lib/chart_grid.js +++ b/src/ui/public/vislib/lib/chart_grid.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; diff --git a/src/ui/public/vislib/lib/chart_title.js b/src/ui/public/vislib/lib/chart_title.js index 5fbbece3ff669f..df28428dcd03e2 100644 --- a/src/ui/public/vislib/lib/chart_title.js +++ b/src/ui/public/vislib/lib/chart_title.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import { VislibLibErrorHandlerProvider } from './_error_handler'; diff --git a/src/ui/public/vislib/lib/data.js b/src/ui/public/vislib/lib/data.js index 4d4190ed786a4e..e88722c5391234 100644 --- a/src/ui/public/vislib/lib/data.js +++ b/src/ui/public/vislib/lib/data.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import { VislibComponentsZeroInjectionInjectZerosProvider } from '../components/zero_injection/inject_zeros'; diff --git a/src/ui/public/vislib/lib/dispatch.js b/src/ui/public/vislib/lib/dispatch.js index 50b533103be6b7..c73bfa625c930b 100644 --- a/src/ui/public/vislib/lib/dispatch.js +++ b/src/ui/public/vislib/lib/dispatch.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; diff --git a/src/ui/public/vislib/lib/handler.js b/src/ui/public/vislib/lib/handler.js index d5ce92cf005bed..c370d5189f5547 100644 --- a/src/ui/public/vislib/lib/handler.js +++ b/src/ui/public/vislib/lib/handler.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import MarkdownIt from 'markdown-it'; diff --git a/src/ui/public/vislib/lib/layout/index.js b/src/ui/public/vislib/lib/layout/index.js index 1286be1b288108..c2fbff71b25af7 100644 --- a/src/ui/public/vislib/lib/layout/index.js +++ b/src/ui/public/vislib/lib/layout/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { VislibLibLayoutLayoutProvider } from './layout'; diff --git a/src/ui/public/vislib/lib/layout/layout.js b/src/ui/public/vislib/lib/layout/layout.js index 7c23914d54649a..9e6083caedb6ab 100644 --- a/src/ui/public/vislib/lib/layout/layout.js +++ b/src/ui/public/vislib/lib/layout/layout.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; diff --git a/src/ui/public/vislib/lib/layout/layout_types.js b/src/ui/public/vislib/lib/layout/layout_types.js index d4fbdaf2c52a5e..0ce5a636410723 100644 --- a/src/ui/public/vislib/lib/layout/layout_types.js +++ b/src/ui/public/vislib/lib/layout/layout_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VislibLibLayoutTypesColumnLayoutProvider } from './types/column_layout'; import { VislibLibLayoutTypesPieLayoutProvider } from './types/pie_layout'; import { GaugeLayoutProvider } from './types/gauge_layout'; diff --git a/src/ui/public/vislib/lib/layout/splits/column_chart/chart_split.js b/src/ui/public/vislib/lib/layout/splits/column_chart/chart_split.js index 872d5d42e12b5d..c6c77fb14be0f1 100644 --- a/src/ui/public/vislib/lib/layout/splits/column_chart/chart_split.js +++ b/src/ui/public/vislib/lib/layout/splits/column_chart/chart_split.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; export function VislibLibLayoutSplitsColumnChartChartSplitProvider() { diff --git a/src/ui/public/vislib/lib/layout/splits/column_chart/chart_title_split.js b/src/ui/public/vislib/lib/layout/splits/column_chart/chart_title_split.js index 816073e51e9d7f..c930589b471bf7 100644 --- a/src/ui/public/vislib/lib/layout/splits/column_chart/chart_title_split.js +++ b/src/ui/public/vislib/lib/layout/splits/column_chart/chart_title_split.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import $ from 'jquery'; diff --git a/src/ui/public/vislib/lib/layout/splits/column_chart/x_axis_split.js b/src/ui/public/vislib/lib/layout/splits/column_chart/x_axis_split.js index 0ae67e1ae51610..77053ceca0f0c8 100644 --- a/src/ui/public/vislib/lib/layout/splits/column_chart/x_axis_split.js +++ b/src/ui/public/vislib/lib/layout/splits/column_chart/x_axis_split.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; diff --git a/src/ui/public/vislib/lib/layout/splits/column_chart/y_axis_split.js b/src/ui/public/vislib/lib/layout/splits/column_chart/y_axis_split.js index d857b946959d9a..78f300100ab2d2 100644 --- a/src/ui/public/vislib/lib/layout/splits/column_chart/y_axis_split.js +++ b/src/ui/public/vislib/lib/layout/splits/column_chart/y_axis_split.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; export function VislibLibLayoutSplitsColumnChartYAxisSplitProvider() { diff --git a/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js b/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js index d7cce6568ebede..f00906c651742c 100644 --- a/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js +++ b/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_split.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; // eslint-disable-next-line @elastic/kibana-custom/no-default-export diff --git a/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js b/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js index 52b3fa730de8aa..616d2f1f72dfc3 100644 --- a/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js +++ b/src/ui/public/vislib/lib/layout/splits/gauge_chart/chart_title_split.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; // eslint-disable-next-line @elastic/kibana-custom/no-default-export diff --git a/src/ui/public/vislib/lib/layout/splits/pie_chart/chart_split.js b/src/ui/public/vislib/lib/layout/splits/pie_chart/chart_split.js index 7416b52f8ef72e..3cb4a1740659b6 100644 --- a/src/ui/public/vislib/lib/layout/splits/pie_chart/chart_split.js +++ b/src/ui/public/vislib/lib/layout/splits/pie_chart/chart_split.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; export function VislibLibLayoutSplitsPieChartChartSplitProvider() { diff --git a/src/ui/public/vislib/lib/layout/splits/pie_chart/chart_title_split.js b/src/ui/public/vislib/lib/layout/splits/pie_chart/chart_title_split.js index a3402b9c4fb7fe..c94a4b9b9fa034 100644 --- a/src/ui/public/vislib/lib/layout/splits/pie_chart/chart_title_split.js +++ b/src/ui/public/vislib/lib/layout/splits/pie_chart/chart_title_split.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; export function VislibLibLayoutSplitsPieChartChartTitleSplitProvider() { diff --git a/src/ui/public/vislib/lib/layout/types/column_layout.js b/src/ui/public/vislib/lib/layout/types/column_layout.js index d270dfac90261e..849f011d02423a 100644 --- a/src/ui/public/vislib/lib/layout/types/column_layout.js +++ b/src/ui/public/vislib/lib/layout/types/column_layout.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VislibLibLayoutSplitsColumnChartChartSplitProvider } from '../splits/column_chart/chart_split'; import { VislibLibLayoutSplitsColumnChartYAxisSplitProvider } from '../splits/column_chart/y_axis_split'; import { VislibLibLayoutSplitsColumnChartXAxisSplitProvider } from '../splits/column_chart/x_axis_split'; diff --git a/src/ui/public/vislib/lib/layout/types/gauge_layout.js b/src/ui/public/vislib/lib/layout/types/gauge_layout.js index 05e35a8065a5dc..1e1b7d104b999a 100644 --- a/src/ui/public/vislib/lib/layout/types/gauge_layout.js +++ b/src/ui/public/vislib/lib/layout/types/gauge_layout.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import GaugeChartSplitProvider from '../splits/gauge_chart/chart_split'; //import VislibLibLayoutSplitsPieChartChartTitleSplitProvider from '../splits/gauge_chart/chart_title_split'; export function GaugeLayoutProvider(Private) { diff --git a/src/ui/public/vislib/lib/layout/types/pie_layout.js b/src/ui/public/vislib/lib/layout/types/pie_layout.js index e27465a90921e8..0cf4548d361bb5 100644 --- a/src/ui/public/vislib/lib/layout/types/pie_layout.js +++ b/src/ui/public/vislib/lib/layout/types/pie_layout.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VislibLibLayoutSplitsPieChartChartSplitProvider } from '../splits/pie_chart/chart_split'; import { VislibLibLayoutSplitsPieChartChartTitleSplitProvider } from '../splits/pie_chart/chart_title_split'; diff --git a/src/ui/public/vislib/lib/types/gauge.js b/src/ui/public/vislib/lib/types/gauge.js index 74500b44b7ab59..694833b73656fb 100644 --- a/src/ui/public/vislib/lib/types/gauge.js +++ b/src/ui/public/vislib/lib/types/gauge.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function vislibGaugeProvider() { return function (config) { diff --git a/src/ui/public/vislib/lib/types/index.js b/src/ui/public/vislib/lib/types/index.js index 53f1b41610f288..e90176446510a2 100644 --- a/src/ui/public/vislib/lib/types/index.js +++ b/src/ui/public/vislib/lib/types/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VislibTypesPointSeries } from './point_series'; import { VislibPieConfigProvider } from './pie'; import { vislibGaugeProvider } from './gauge'; diff --git a/src/ui/public/vislib/lib/types/pie.js b/src/ui/public/vislib/lib/types/pie.js index ec66cd2778f392..bc4e8a41520953 100644 --- a/src/ui/public/vislib/lib/types/pie.js +++ b/src/ui/public/vislib/lib/types/pie.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function VislibPieConfigProvider() { diff --git a/src/ui/public/vislib/lib/types/point_series.js b/src/ui/public/vislib/lib/types/point_series.js index e9410466add3c9..36df39d39d1836 100644 --- a/src/ui/public/vislib/lib/types/point_series.js +++ b/src/ui/public/vislib/lib/types/point_series.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function VislibTypesPointSeries() { diff --git a/src/ui/public/vislib/lib/vis_config.js b/src/ui/public/vislib/lib/vis_config.js index 5c51da198fd1e6..88f7d864b516a2 100644 --- a/src/ui/public/vislib/lib/vis_config.js +++ b/src/ui/public/vislib/lib/vis_config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Provides vislib configuration, throws error if invalid property is accessed without providing defaults */ diff --git a/src/ui/public/vislib/vis.js b/src/ui/public/vislib/vis.js index 3857b910f2956d..b64bdc93f9bbf9 100644 --- a/src/ui/public/vislib/vis.js +++ b/src/ui/public/vislib/vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import d3 from 'd3'; import { KbnError } from '../errors'; diff --git a/src/ui/public/vislib/vislib.js b/src/ui/public/vislib/vislib.js index c0fc5606f0f8ae..f8b6faa841a2dc 100644 --- a/src/ui/public/vislib/vislib.js +++ b/src/ui/public/vislib/vislib.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './lib/types/pie'; import './lib/types/point_series'; import './lib/types'; diff --git a/src/ui/public/vislib/visualizations/_chart.js b/src/ui/public/vislib/visualizations/_chart.js index f66508981c2f3d..9c0659478483b1 100644 --- a/src/ui/public/vislib/visualizations/_chart.js +++ b/src/ui/public/vislib/visualizations/_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import { dataLabel } from '../lib/_data_label'; diff --git a/src/ui/public/vislib/visualizations/gauge_chart.js b/src/ui/public/vislib/visualizations/gauge_chart.js index 17e8119016410a..113f5e21751fdb 100644 --- a/src/ui/public/vislib/visualizations/gauge_chart.js +++ b/src/ui/public/vislib/visualizations/gauge_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import $ from 'jquery'; import { VislibVisualizationsChartProvider } from './_chart'; diff --git a/src/ui/public/vislib/visualizations/gauges/gauge_types.js b/src/ui/public/vislib/visualizations/gauges/gauge_types.js index 498e48dbbdc946..3c9b0e77f66da5 100644 --- a/src/ui/public/vislib/visualizations/gauges/gauge_types.js +++ b/src/ui/public/vislib/visualizations/gauges/gauge_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { MeterGaugeProvider } from './meter'; export function GaugeTypesProvider(Private) { diff --git a/src/ui/public/vislib/visualizations/gauges/meter.js b/src/ui/public/vislib/visualizations/gauges/meter.js index 47920971aabe0b..f4832db054e03e 100644 --- a/src/ui/public/vislib/visualizations/gauges/meter.js +++ b/src/ui/public/vislib/visualizations/gauges/meter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import { getHeatmapColors } from '../../components/color/heatmap_color'; diff --git a/src/ui/public/vislib/visualizations/pie_chart.js b/src/ui/public/vislib/visualizations/pie_chart.js index d69d3d72be77c4..0889bd820dc597 100644 --- a/src/ui/public/vislib/visualizations/pie_chart.js +++ b/src/ui/public/vislib/visualizations/pie_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; diff --git a/src/ui/public/vislib/visualizations/point_series.js b/src/ui/public/vislib/visualizations/point_series.js index 5f4837b1a13490..93bd4bae5dc4f3 100644 --- a/src/ui/public/vislib/visualizations/point_series.js +++ b/src/ui/public/vislib/visualizations/point_series.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; diff --git a/src/ui/public/vislib/visualizations/point_series/_point_series.js b/src/ui/public/vislib/visualizations/point_series/_point_series.js index 347e503f997960..a1cd8a403b0e90 100644 --- a/src/ui/public/vislib/visualizations/point_series/_point_series.js +++ b/src/ui/public/vislib/visualizations/point_series/_point_series.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function VislibVisualizationsPointSeriesProvider() { diff --git a/src/ui/public/vislib/visualizations/point_series/area_chart.js b/src/ui/public/vislib/visualizations/point_series/area_chart.js index 0464687f44e85c..a8b3bd1bf1a79a 100644 --- a/src/ui/public/vislib/visualizations/point_series/area_chart.js +++ b/src/ui/public/vislib/visualizations/point_series/area_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import $ from 'jquery'; diff --git a/src/ui/public/vislib/visualizations/point_series/column_chart.js b/src/ui/public/vislib/visualizations/point_series/column_chart.js index ec05958096f009..7d43d4b47e9242 100644 --- a/src/ui/public/vislib/visualizations/point_series/column_chart.js +++ b/src/ui/public/vislib/visualizations/point_series/column_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { VislibVisualizationsPointSeriesProvider } from './_point_series'; diff --git a/src/ui/public/vislib/visualizations/point_series/heatmap_chart.js b/src/ui/public/vislib/visualizations/point_series/heatmap_chart.js index bafb1f55c6116f..9d33f222d34178 100644 --- a/src/ui/public/vislib/visualizations/point_series/heatmap_chart.js +++ b/src/ui/public/vislib/visualizations/point_series/heatmap_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import moment from 'moment'; import { VislibVisualizationsPointSeriesProvider } from './_point_series'; diff --git a/src/ui/public/vislib/visualizations/point_series/line_chart.js b/src/ui/public/vislib/visualizations/point_series/line_chart.js index ad2a653baab7cc..478e8fc60ad952 100644 --- a/src/ui/public/vislib/visualizations/point_series/line_chart.js +++ b/src/ui/public/vislib/visualizations/point_series/line_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import _ from 'lodash'; import { VislibVisualizationsPointSeriesProvider } from './_point_series'; diff --git a/src/ui/public/vislib/visualizations/point_series/series_types.js b/src/ui/public/vislib/visualizations/point_series/series_types.js index 8f47d6e4db2fda..f7411ed2dd3ee0 100644 --- a/src/ui/public/vislib/visualizations/point_series/series_types.js +++ b/src/ui/public/vislib/visualizations/point_series/series_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VislibVisualizationsColumnChartProvider } from './column_chart'; import { VislibVisualizationsLineChartProvider } from './line_chart'; import { VislibVisualizationsAreaChartProvider } from './area_chart'; diff --git a/src/ui/public/vislib/visualizations/time_marker.js b/src/ui/public/vislib/visualizations/time_marker.js index 57e6003fcdaed7..8775064db65c00 100644 --- a/src/ui/public/vislib/visualizations/time_marker.js +++ b/src/ui/public/vislib/visualizations/time_marker.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import d3 from 'd3'; import dateMath from '@kbn/datemath'; diff --git a/src/ui/public/vislib/visualizations/vis_types.js b/src/ui/public/vislib/visualizations/vis_types.js index 684a434e66a870..25f949ccd7efe0 100644 --- a/src/ui/public/vislib/visualizations/vis_types.js +++ b/src/ui/public/vislib/visualizations/vis_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VislibVisualizationsPointSeriesProvider } from './point_series'; import { VislibVisualizationsPieChartProvider } from './pie_chart'; import { GaugeChartProvider } from './gauge_chart'; diff --git a/src/ui/public/visualize/__tests__/spy.js b/src/ui/public/visualize/__tests__/spy.js index 92fe4768feaa98..0a445dfbd67b33 100644 --- a/src/ui/public/visualize/__tests__/spy.js +++ b/src/ui/public/visualize/__tests__/spy.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import sinon from 'sinon'; import { expect } from 'chai'; diff --git a/src/ui/public/visualize/__tests__/visualization_editor.js b/src/ui/public/visualize/__tests__/visualization_editor.js index da97e562f8e608..15611509186f1b 100644 --- a/src/ui/public/visualize/__tests__/visualization_editor.js +++ b/src/ui/public/visualize/__tests__/visualization_editor.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import expect from 'expect.js'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/visualize/__tests__/visualize.js b/src/ui/public/visualize/__tests__/visualize.js index 48007c188c2e58..77a9f288be817c 100644 --- a/src/ui/public/visualize/__tests__/visualize.js +++ b/src/ui/public/visualize/__tests__/visualize.js @@ -1,10 +1,31 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import expect from 'expect.js'; import ngMock from 'ng_mock'; +import sinon from 'sinon'; import { VisProvider } from '../../vis'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import FixturesStubbedSearchSourceProvider from 'fixtures/stubbed_search_source'; import MockState from 'fixtures/mock_state'; +import { PersistedState } from '../../persisted_state'; describe('visualize directive', function () { let $rootScope; @@ -16,6 +37,7 @@ describe('visualize directive', function () { let fixtures; let searchSource; let appState; + let uiState; beforeEach(ngMock.module('kibana', 'kibana/table_vis')); beforeEach(ngMock.inject(function (Private, $injector) { @@ -25,11 +47,11 @@ describe('visualize directive', function () { Vis = Private(VisProvider); appState = new MockState({ filters: [] }); appState.toJSON = () => { return {}; }; + uiState = new PersistedState({}); indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); searchSource = Private(FixturesStubbedSearchSourceProvider); - const requiresSearch = false; - init(new CreateVis(null, requiresSearch), fixtures.oneRangeBucket); + init(new CreateVis(null), fixtures.oneRangeBucket); })); afterEach(() => { @@ -42,7 +64,7 @@ describe('visualize directive', function () { $rootScope.vis = vis; $rootScope.esResponse = esResponse; - $rootScope.uiState = require('fixtures/mock_ui_state'); + $rootScope.uiState = uiState; $rootScope.appState = appState; $rootScope.appState.vis = vis.getState(); $rootScope.searchSource = searchSource; @@ -57,7 +79,7 @@ describe('visualize directive', function () { $scope = $el.isolateScope(); } - function CreateVis(params, requiresSearch) { + function CreateVis(params, requestHandler = 'none') { const vis = new Vis(indexPattern, { type: 'table', params: params || {}, @@ -77,7 +99,7 @@ describe('visualize directive', function () { ] }); - vis.type.requestHandler = requiresSearch ? 'default' : 'none'; + vis.type.requestHandler = requestHandler; vis.type.responseHandler = 'none'; vis.type.requiresSearch = false; return vis; @@ -103,9 +125,79 @@ describe('visualize directive', function () { expect($scope.appState.vis).to.not.equal({}); }); - it('sets force flag on force event', () => { - $scope.vis.emit('reload'); - expect($scope.vis.reload).to.equal(true); + describe('request handler', () => { + + const requestHandler = sinon.stub().resolves(); + + /** + * Asserts that a specific parameter had a specific value in the last call to the requestHandler. + */ + function assertParam(obj) { + sinon.assert.calledWith(requestHandler, sinon.match.any, sinon.match(obj)); + } + + /** + * Wait for the next $scope.fetch call. + * Since we use an old lodash version we cannot use fake timers here. + */ + function waitForFetch() { + return new Promise(resolve => { setTimeout(resolve, 150); }); + } + + beforeEach(() => { + init(new CreateVis(null, requestHandler), fixtures.oneRangeBucket); + }); + + afterEach(() => { + requestHandler.resetHistory(); + }); + + describe('forceFetch param', () => { + it('should be true if triggered via vis.forceReload', async () => { + $scope.vis.forceReload(); + await waitForFetch(); + sinon.assert.calledOnce(requestHandler); + assertParam({ forceFetch: true }); + }); + + it('should be true if triggered via courier:searchRefresh event', async () => { + $scope.$emit('courier:searchRefresh'); + await waitForFetch(); + sinon.assert.calledOnce(requestHandler); + assertParam({ forceFetch: true }); + }); + + it('should be true if triggered via fetch event', async () => { + $scope.$emit('fetch'); + await waitForFetch(); + sinon.assert.calledOnce(requestHandler); + assertParam({ forceFetch: true }); + }); + + it('should be false if triggered via resize event', async () => { + $el.width(400); + $el.height(500); + await waitForFetch(); + sinon.assert.calledOnce(requestHandler); + assertParam({ forceFetch: false }); + }); + + it('should be false if triggered via uiState change', async () => { + uiState.set('foo', 'bar'); + await waitForFetch(); + sinon.assert.calledOnce(requestHandler); + assertParam({ forceFetch: false }); + }); + + it('should be true if at least one trigger required it to be true', async () => { + $el.width(400); + $scope.vis.forceReload(); // This requires forceFetch to be true + uiState.set('foo', 'bar'); + await waitForFetch(); + sinon.assert.calledOnce(requestHandler); + assertParam({ forceFetch: true }); + }); + }); }); }); diff --git a/src/ui/public/visualize/__tests__/visualize_legend.js b/src/ui/public/visualize/__tests__/visualize_legend.js index b726d17699c23c..04b1b60612570d 100644 --- a/src/ui/public/visualize/__tests__/visualize_legend.js +++ b/src/ui/public/visualize/__tests__/visualize_legend.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import _ from 'lodash'; import expect from 'expect.js'; diff --git a/src/ui/public/visualize/index.js b/src/ui/public/visualize/index.js index 075c8e0b591588..b3dceae8dcd091 100644 --- a/src/ui/public/visualize/index.js +++ b/src/ui/public/visualize/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './visualize'; diff --git a/src/ui/public/visualize/loader/__tests__/loader.js b/src/ui/public/visualize/loader/__tests__/loader.js index f697ee06a73a0c..87c687506e2e61 100644 --- a/src/ui/public/visualize/loader/__tests__/loader.js +++ b/src/ui/public/visualize/loader/__tests__/loader.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import angular from 'angular'; import expect from 'expect.js'; import ngMock from 'ng_mock'; @@ -78,7 +97,7 @@ describe('visualize loader', () => { // Setup savedObject mockedSavedObject = createSavedObject(); // Mock savedVisualizations.get to return 'mockedSavedObject' when id is 'exists' - sinon.stub(savedVisualizations, 'get', (id) => + sinon.stub(savedVisualizations, 'get').callsFake((id) => id === 'exists' ? Promise.resolve(mockedSavedObject) : Promise.reject() ); })); @@ -251,7 +270,7 @@ describe('visualize loader', () => { expect(spy.notCalled).to.be(true); container.find('visualize').trigger('renderComplete'); expect(spy.calledOnce).to.be(true); - spy.reset(); + spy.resetHistory(); handler.removeRenderCompleteListener(spy); container.find('visualize').trigger('renderComplete'); expect(spy.notCalled).to.be(true); @@ -268,6 +287,42 @@ describe('visualize loader', () => { await timeout(); expect(spy.calledOnce).to.be(true); }); + + it('should allow updating and deleting data attributes', () => { + const container = newContainer(); + const handler = loader.embedVisualizationWithSavedObject(container, createSavedObject(), { + dataAttrs: { + foo: 42 + } + }); + expect(container.find('visualize').attr('data-foo')).to.be('42'); + handler.update({ + dataAttrs: { + foo: null, + added: 'value', + } + }); + // Synce we are relying on $evalAsync we need to trigger a digest loop during tests + $rootScope.$digest(); + expect(container.find('visualize')[0].hasAttribute('data-foo')).to.be(false); + expect(container.find('visualize').attr('data-added')).to.be('value'); + }); + + it('should allow updating the time range of the visualization', () => { + const handler = loader.embedVisualizationWithSavedObject(newContainer(), createSavedObject(), { + timeRange: { from: 'now-7d', to: 'now' } + }); + handler.update({ + timeRange: { from: 'now-10d/d', to: 'now' } + }); + // Synce we are relying on $evalAsync we need to trigger a digest loop during tests + $rootScope.$digest(); + // This is not the best test, since it tests internal structure of our scope. + // Unfortunately we currently don't expose the timeRange in a better way. + // Once we rewrite this to a react component we should spy on the timeRange + // property in the component to match the passed in value. + expect(handler._scope.timeRange).to.eql({ from: 'now-10d/d', to: 'now' }); + }); }); }); diff --git a/src/ui/public/visualize/loader/embedded_visualize_handler.js b/src/ui/public/visualize/loader/embedded_visualize_handler.js index a6d8f943448b69..f3641aeccd8118 100644 --- a/src/ui/public/visualize/loader/embedded_visualize_handler.js +++ b/src/ui/public/visualize/loader/embedded_visualize_handler.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { EventEmitter } from 'events'; const RENDER_COMPLETE_EVENT = 'render_complete'; @@ -20,6 +39,32 @@ export class EmbeddedVisualizeHandler { }); } + /** + * Update properties of the embedded visualization. This method does not allow + * updating all initial parameters, but only a subset of the ones allowed + * in {@link VisualizeLoaderParams}. + * + * @param {Object} [params={}] The parameters that should be updated. + * @property {Object} [timeRange] A new time range for this visualization. + * @property {Object} [dataAttrs] An object of data attributes to modify. The + * key will be the name of the data attribute and the value the value that + * attribute will get. Use null to remove a specific data attribute from the visualization. + */ + update(params = {}) { + this._scope.$evalAsync(() => { + if (params.hasOwnProperty('timeRange')) { + this._scope.timeRange = params.timeRange; + } + + // Apply data- attributes to the element if specified + if (params.dataAttrs) { + Object.keys(params.dataAttrs).forEach(key => { + this._element.attr(`data-${key}`, params.dataAttrs[key]); + }); + } + }); + } + /** * Destroy the underlying Angular scope of the visualization. This should be * called whenever you remove the visualization. diff --git a/src/ui/public/visualize/loader/index.js b/src/ui/public/visualize/loader/index.js index 3f3b9e6635d5bd..46a8968358294e 100644 --- a/src/ui/public/visualize/loader/index.js +++ b/src/ui/public/visualize/loader/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export * from './loader'; diff --git a/src/ui/public/visualize/loader/loader.js b/src/ui/public/visualize/loader/loader.js index 6742247df8c4f7..8fa679de49dac7 100644 --- a/src/ui/public/visualize/loader/loader.js +++ b/src/ui/public/visualize/loader/loader.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * IMPORTANT: If you make changes to this API, please make sure to check that * the docs (docs/development/visualize/development-create-visualization.asciidoc) diff --git a/src/ui/public/visualize/spy.js b/src/ui/public/visualize/spy.js index 14bc334ad35cde..0c5442a941aa7e 100644 --- a/src/ui/public/visualize/spy.js +++ b/src/ui/public/visualize/spy.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import $ from 'jquery'; import { SpyModesRegistryProvider } from '../registry/spy_modes'; import { uiModules } from '../modules'; diff --git a/src/ui/public/visualize/visualization.js b/src/ui/public/visualize/visualization.js index 029c979224d806..f1096ef15cf30b 100644 --- a/src/ui/public/visualize/visualization.js +++ b/src/ui/public/visualize/visualization.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Observable } from 'rxjs/Rx'; import './spy'; import './visualize.less'; diff --git a/src/ui/public/visualize/visualization_editor.js b/src/ui/public/visualize/visualization_editor.js index 032cdd032a0a7e..784632e410e7c1 100644 --- a/src/ui/public/visualize/visualization_editor.js +++ b/src/ui/public/visualize/visualization_editor.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './spy'; import './visualize.less'; import './visualize_legend'; diff --git a/src/ui/public/visualize/visualize.js b/src/ui/public/visualize/visualize.js index d31816e1d51d56..bde03e3bf88400 100644 --- a/src/ui/public/visualize/visualize.js +++ b/src/ui/public/visualize/visualize.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { uiModules } from '../modules'; import { stateMonitorFactory } from '../state_management/state_monitor_factory'; @@ -40,6 +59,7 @@ uiModules template: visualizeTemplate, link: async function ($scope, $el) { let destroyed = false; + let forceFetch = false; if (!$scope.savedObj) throw(`saved object was not provided to directive`); if (!$scope.appState) $scope.appState = getAppState(); @@ -87,7 +107,12 @@ uiModules queryFilter: queryFilter, searchSource: $scope.savedObj.searchSource, timeRange: timeRange, + forceFetch, }; + + // Reset forceFetch flag, since we are now executing our forceFetch in case it was true + forceFetch = false; + // searchSource is only there for courier request handler requestHandler($scope.vis, handlerParams) .then(requestHandlerResponse => { @@ -135,7 +160,7 @@ uiModules const reload = () => { - $scope.vis.reload = true; + forceFetch = true; $scope.fetch(); }; $scope.vis.on('reload', reload); diff --git a/src/ui/public/visualize/visualize_legend.js b/src/ui/public/visualize/visualize_legend.js index 8420d91687e923..85d2ff6c903279 100644 --- a/src/ui/public/visualize/visualize_legend.js +++ b/src/ui/public/visualize/visualize_legend.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import html from './visualize_legend.html'; import { VislibLibDataProvider } from '../vislib/lib/data'; diff --git a/src/ui/public/watch_multi/__tests__/watch_multi.js b/src/ui/public/watch_multi/__tests__/watch_multi.js index 8e45fbe1960d66..4a4bd0fa0054c9 100644 --- a/src/ui/public/watch_multi/__tests__/watch_multi.js +++ b/src/ui/public/watch_multi/__tests__/watch_multi.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import ngMock from 'ng_mock'; diff --git a/src/ui/public/watch_multi/index.js b/src/ui/public/watch_multi/index.js index 359d92b92f027c..3f0f43ce27ed2d 100644 --- a/src/ui/public/watch_multi/index.js +++ b/src/ui/public/watch_multi/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import './watch_multi'; diff --git a/src/ui/public/watch_multi/watch_multi.js b/src/ui/public/watch_multi/watch_multi.js index 5d43066bf8d501..0139ca8133daf9 100644 --- a/src/ui/public/watch_multi/watch_multi.js +++ b/src/ui/public/watch_multi/watch_multi.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { uiModules } from '../modules'; import { callEach } from '../utils/function'; diff --git a/src/ui/tutorials_mixin.js b/src/ui/tutorials_mixin.js index 766cf1dce1e897..7ab14bfc45080d 100644 --- a/src/ui/tutorials_mixin.js +++ b/src/ui/tutorials_mixin.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import Joi from 'joi'; import { tutorialSchema } from '../core_plugins/kibana/common/tutorials/tutorial_schema'; diff --git a/src/ui/ui_apps/__tests__/ui_app.js b/src/ui/ui_apps/__tests__/ui_app.js index 6ac0f60f3120f0..a923f544d9c692 100644 --- a/src/ui/ui_apps/__tests__/ui_app.js +++ b/src/ui/ui_apps/__tests__/ui_app.js @@ -1,12 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; -import Chance from 'chance'; import { UiApp } from '../ui_app'; import { UiNavLink } from '../../ui_nav_links'; -const chance = new Chance(); - function createStubUiAppSpec(extraParams) { return { id: 'uiapp-test', @@ -18,11 +34,6 @@ function createStubUiAppSpec(extraParams) { linkToLastSubUrl: true, hidden: false, listed: false, - uses: [ - 'visTypes', - 'chromeNavControls', - 'hacks', - ], ...extraParams }; } @@ -30,13 +41,6 @@ function createStubUiAppSpec(extraParams) { function createStubKbnServer() { return { plugins: [], - uiExports: { - appExtensions: { - hacks: [ - 'plugins/foo/hack' - ] - } - }, config: { get: sinon.stub() .withArgs('server.basePath') @@ -129,7 +133,6 @@ describe('ui apps / UiApp', () => { it('includes main and hack modules', () => { expect(app.getModules()).to.eql([ 'main.js', - 'plugins/foo/hack' ]); }); @@ -305,34 +308,5 @@ describe('ui apps / UiApp', () => { const app = createUiApp({ id: 'foo', main: 'bar' }); expect(app.getModules()).to.eql(['bar']); }); - - it('returns appExtensions for used types only, in alphabetical order, starting with main module', () => { - const kbnServer = createStubKbnServer(); - kbnServer.uiExports.appExtensions = { - abc: chance.shuffle([ - 'a', - 'b', - 'c', - ]), - def: chance.shuffle([ - 'd', - 'e', - 'f', - ]) - }; - - const appExtensionType = chance.shuffle(Object.keys(kbnServer.uiExports.appExtensions))[0]; - const appSpec = { - id: 'foo', - main: 'bar', - uses: [appExtensionType], - }; - - const app = createUiApp(appSpec, kbnServer); - expect(app.getModules()).to.eql([ - 'bar', - ...appExtensionType.split(''), - ]); - }); }); }); diff --git a/src/ui/ui_apps/index.js b/src/ui/ui_apps/index.js index d2914dc94e0527..d64848b2c1a92d 100644 --- a/src/ui/ui_apps/index.js +++ b/src/ui/ui_apps/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { uiAppsMixin } from './ui_apps_mixin'; diff --git a/src/ui/ui_apps/ui_app.js b/src/ui/ui_apps/ui_app.js index 9f9c73bd8d345d..bea6ec65f7e4ce 100644 --- a/src/ui/ui_apps/ui_app.js +++ b/src/ui/ui_apps/ui_app.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { UiNavLink } from '../ui_nav_links'; export class UiApp { @@ -14,7 +33,6 @@ export class UiApp { linkToLastSubUrl, listed, url = `/app/${id}`, - uses = [] } = spec; if (!id) { @@ -38,18 +56,6 @@ export class UiApp { throw new Error(`Unknown plugin id "${this._pluginId}"`); } - const { appExtensions = [] } = kbnServer.uiExports; - this._modules = [].concat( - this._main || [], - uses - // flatten appExtensions for used types - .reduce((acc, type) => acc.concat(appExtensions[type] || []), []) - // de-dupe app extension module ids - .reduce((acc, item) => !item || acc.includes(item) ? acc : acc.concat(item), []) - // sort app extension module ids alphabetically - .sort((a, b) => a.localeCompare(b)) - ); - if (!this.isHidden()) { // unless an app is hidden it gets a navlink, but we only respond to `getNavLink()` // if the app is also listed. This means that all apps in the kibanaPayload will @@ -93,7 +99,7 @@ export class UiApp { } getModules() { - return this._modules; + return this._main ? [this._main] : []; } _getPlugin() { diff --git a/src/ui/ui_apps/ui_apps_mixin.js b/src/ui/ui_apps/ui_apps_mixin.js index 9238c210e34cde..cf69f9170dbafd 100644 --- a/src/ui/ui_apps/ui_apps_mixin.js +++ b/src/ui/ui_apps/ui_apps_mixin.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { UiApp } from './ui_app'; export function uiAppsMixin(kbnServer, server) { diff --git a/src/ui/ui_apps/ui_apps_mixin.test.js b/src/ui/ui_apps/ui_apps_mixin.test.js index 2446b0622704d6..2b85c36f2a679b 100644 --- a/src/ui/ui_apps/ui_apps_mixin.test.js +++ b/src/ui/ui_apps/ui_apps_mixin.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiAppsMixin } from './ui_apps_mixin'; jest.mock('./ui_app', () => ({ diff --git a/src/ui/ui_bundles/__tests__/app_entry_template.js b/src/ui/ui_bundles/__tests__/app_entry_template.js index 1eb475f208f77e..c026c3b7590527 100644 --- a/src/ui/ui_bundles/__tests__/app_entry_template.js +++ b/src/ui/ui_bundles/__tests__/app_entry_template.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; diff --git a/src/ui/ui_bundles/__tests__/ui_bundle.js b/src/ui/ui_bundles/__tests__/ui_bundle.js index 9b4376d1e3d4d4..f92cc79303ce62 100644 --- a/src/ui/ui_bundles/__tests__/ui_bundle.js +++ b/src/ui/ui_bundles/__tests__/ui_bundle.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { UiBundle } from '../ui_bundle'; diff --git a/src/ui/ui_bundles/app_entry_template.js b/src/ui/ui_bundles/app_entry_template.js index 2f2715e9634d0b..2dd8d612e80701 100644 --- a/src/ui/ui_bundles/app_entry_template.js +++ b/src/ui/ui_bundles/app_entry_template.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const appEntryTemplate = (bundle) => ` /** * Test entry file diff --git a/src/ui/ui_bundles/index.js b/src/ui/ui_bundles/index.js index b9207b5204dbfc..b6afcf71a11147 100644 --- a/src/ui/ui_bundles/index.js +++ b/src/ui/ui_bundles/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { uiBundlesMixin } from './ui_bundles_mixin'; diff --git a/src/ui/ui_bundles/ui_bundle.js b/src/ui/ui_bundles/ui_bundle.js index 79f77d2bd5eeb1..34aeaa2a43994a 100644 --- a/src/ui/ui_bundles/ui_bundle.js +++ b/src/ui/ui_bundles/ui_bundle.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fromNode as fcb } from 'bluebird'; import { readFile, writeFile, unlink, stat } from 'fs'; diff --git a/src/ui/ui_bundles/ui_bundles_controller.js b/src/ui/ui_bundles/ui_bundles_controller.js index f80f0fd1ada05b..d63dfb963c90b3 100644 --- a/src/ui/ui_bundles/ui_bundles_controller.js +++ b/src/ui/ui_bundles/ui_bundles_controller.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { createHash } from 'crypto'; import { resolve } from 'path'; @@ -44,6 +63,8 @@ export class UiBundlesController { matchBase: true }); + this._appExtensions = uiExports.appExtensions || {}; + this._webpackAliases = { ...getWebpackAliases(pluginSpecs), ...uiExports.webpackAliases @@ -103,6 +124,10 @@ export class UiBundlesController { return this._webpackAliases; } + getAppExtensions() { + return this._appExtensions; + } + isDevMode() { return this._env === 'development'; } diff --git a/src/ui/ui_bundles/ui_bundles_mixin.js b/src/ui/ui_bundles/ui_bundles_mixin.js index 9c39883c19dfe6..6127cb9ecd1439 100644 --- a/src/ui/ui_bundles/ui_bundles_mixin.js +++ b/src/ui/ui_bundles/ui_bundles_mixin.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { UiBundlesController } from './ui_bundles_controller'; export async function uiBundlesMixin(kbnServer) { diff --git a/src/ui/ui_exports/__tests__/collect_ui_exports.js b/src/ui/ui_exports/__tests__/collect_ui_exports.js index 9609a4a95c12b5..2a7464e58c8d09 100644 --- a/src/ui/ui_exports/__tests__/collect_ui_exports.js +++ b/src/ui/ui_exports/__tests__/collect_ui_exports.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { PluginPack } from '../../../plugin_discovery'; diff --git a/src/ui/ui_exports/collect_ui_exports.js b/src/ui/ui_exports/collect_ui_exports.js index 2bc3efe400b677..3fda38b3e31a37 100644 --- a/src/ui/ui_exports/collect_ui_exports.js +++ b/src/ui/ui_exports/collect_ui_exports.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { UI_EXPORT_DEFAULTS } from './ui_export_defaults'; import * as uiExportTypeReducers from './ui_export_types'; import { reduceExportSpecs } from '../../plugin_discovery'; diff --git a/src/ui/ui_exports/index.js b/src/ui/ui_exports/index.js index a9a1e989fbe729..f74553c70e0bf1 100644 --- a/src/ui/ui_exports/index.js +++ b/src/ui/ui_exports/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { collectUiExports } from './collect_ui_exports'; export { uiExportsMixin } from './ui_exports_mixin'; diff --git a/src/ui/ui_exports/ui_export_defaults.js b/src/ui/ui_exports/ui_export_defaults.js index 29f15669f043f2..16dae9db466872 100644 --- a/src/ui/ui_exports/ui_export_defaults.js +++ b/src/ui/ui_exports/ui_export_defaults.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { dirname, resolve } from 'path'; const ROOT = dirname(require.resolve('../../../package.json')); diff --git a/src/ui/ui_exports/ui_export_types/index.js b/src/ui/ui_exports/ui_export_types/index.js index 1d60f002702e31..394292550d324c 100644 --- a/src/ui/ui_exports/ui_export_types/index.js +++ b/src/ui/ui_exports/ui_export_types/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { injectDefaultVars, replaceInjectedVars, @@ -24,6 +43,7 @@ export { spyModes, chromeNavControls, navbarExtensions, + dashboardPanelActions, managementSections, devTools, docViews, diff --git a/src/ui/ui_exports/ui_export_types/modify_injected_vars.js b/src/ui/ui_exports/ui_export_types/modify_injected_vars.js index 2a26bc98aa4d32..4bb9f350bd9596 100644 --- a/src/ui/ui_exports/ui_export_types/modify_injected_vars.js +++ b/src/ui/ui_exports/ui_export_types/modify_injected_vars.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { flatConcatAtType } from './reduce'; import { wrap, alias, mapSpec } from './modify_reduce'; diff --git a/src/ui/ui_exports/ui_export_types/modify_reduce/alias.js b/src/ui/ui_exports/ui_export_types/modify_reduce/alias.js index 8a13fa7a12ae56..5ab352a018d488 100644 --- a/src/ui/ui_exports/ui_export_types/modify_reduce/alias.js +++ b/src/ui/ui_exports/ui_export_types/modify_reduce/alias.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Creates a reducer wrapper which, when called with a reducer, creates a new * reducer that replaces the `type` value with `newType` before delegating to diff --git a/src/ui/ui_exports/ui_export_types/modify_reduce/debug.js b/src/ui/ui_exports/ui_export_types/modify_reduce/debug.js index 5c2df3059fae2c..c99095e4a8206e 100644 --- a/src/ui/ui_exports/ui_export_types/modify_reduce/debug.js +++ b/src/ui/ui_exports/ui_export_types/modify_reduce/debug.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { mapSpec } from './map_spec'; /** diff --git a/src/ui/ui_exports/ui_export_types/modify_reduce/index.js b/src/ui/ui_exports/ui_export_types/modify_reduce/index.js index 9c698f304ec6e3..54c81fefdd08a0 100644 --- a/src/ui/ui_exports/ui_export_types/modify_reduce/index.js +++ b/src/ui/ui_exports/ui_export_types/modify_reduce/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { alias } from './alias'; export { debug } from './debug'; export { mapSpec } from './map_spec'; diff --git a/src/ui/ui_exports/ui_export_types/modify_reduce/map_spec.js b/src/ui/ui_exports/ui_export_types/modify_reduce/map_spec.js index 3607e8403c4f53..01bfd181a0c45a 100644 --- a/src/ui/ui_exports/ui_export_types/modify_reduce/map_spec.js +++ b/src/ui/ui_exports/ui_export_types/modify_reduce/map_spec.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Creates a reducer wrapper which, when called with a reducer, creates a new * reducer that replaces the `specs` value with the result of calling diff --git a/src/ui/ui_exports/ui_export_types/modify_reduce/unique_keys.js b/src/ui/ui_exports/ui_export_types/modify_reduce/unique_keys.js index 4d7f3650710f2c..f19f9595d23cf6 100644 --- a/src/ui/ui_exports/ui_export_types/modify_reduce/unique_keys.js +++ b/src/ui/ui_exports/ui_export_types/modify_reduce/unique_keys.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const uniqueKeys = (sourceType) => (next) => (acc, spec, type, pluginSpec) => { const duplicates = Object.keys(spec) .filter(key => acc[type] && acc[type].hasOwnProperty(key)); diff --git a/src/ui/ui_exports/ui_export_types/modify_reduce/wrap.js b/src/ui/ui_exports/ui_export_types/modify_reduce/wrap.js index 55a940192bf585..728d9abfa712dc 100644 --- a/src/ui/ui_exports/ui_export_types/modify_reduce/wrap.js +++ b/src/ui/ui_exports/ui_export_types/modify_reduce/wrap.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Wrap a function with any number of wrappers. Wrappers * are functions that take a reducer and return a reducer diff --git a/src/ui/ui_exports/ui_export_types/reduce/flat_concat_at_type.js b/src/ui/ui_exports/ui_export_types/reduce/flat_concat_at_type.js index b141f2fd605cec..5fcbcac4633927 100644 --- a/src/ui/ui_exports/ui_export_types/reduce/flat_concat_at_type.js +++ b/src/ui/ui_exports/ui_export_types/reduce/flat_concat_at_type.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { createTypeReducer, flatConcat } from './lib'; /** diff --git a/src/ui/ui_exports/ui_export_types/reduce/flat_concat_values_at_type.js b/src/ui/ui_exports/ui_export_types/reduce/flat_concat_values_at_type.js index 085c2867506473..c664038bf9c6a9 100644 --- a/src/ui/ui_exports/ui_export_types/reduce/flat_concat_values_at_type.js +++ b/src/ui/ui_exports/ui_export_types/reduce/flat_concat_values_at_type.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { createTypeReducer, flatConcat, diff --git a/src/ui/ui_exports/ui_export_types/reduce/index.js b/src/ui/ui_exports/ui_export_types/reduce/index.js index e131fe1c261d6b..7dc1ba60fb3cb3 100644 --- a/src/ui/ui_exports/ui_export_types/reduce/index.js +++ b/src/ui/ui_exports/ui_export_types/reduce/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { mergeAtType } from './merge_at_type'; export { flatConcatValuesAtType } from './flat_concat_values_at_type'; export { flatConcatAtType } from './flat_concat_at_type'; diff --git a/src/ui/ui_exports/ui_export_types/reduce/lib/create_type_reducer.js b/src/ui/ui_exports/ui_export_types/reduce/lib/create_type_reducer.js index c5ff343554e27a..c59404a06c0db4 100644 --- a/src/ui/ui_exports/ui_export_types/reduce/lib/create_type_reducer.js +++ b/src/ui/ui_exports/ui_export_types/reduce/lib/create_type_reducer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Creates a reducer that reduces the values within `acc[type]` by calling * reducer with signature: diff --git a/src/ui/ui_exports/ui_export_types/reduce/lib/flat_concat.js b/src/ui/ui_exports/ui_export_types/reduce/lib/flat_concat.js index a61c240836d021..41a1c431b36bac 100644 --- a/src/ui/ui_exports/ui_export_types/reduce/lib/flat_concat.js +++ b/src/ui/ui_exports/ui_export_types/reduce/lib/flat_concat.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Concatenate two values into a single array, ignoring either * value if it is undefined and flattening the value if it is an array diff --git a/src/ui/ui_exports/ui_export_types/reduce/lib/index.js b/src/ui/ui_exports/ui_export_types/reduce/lib/index.js index 79e42849a3f3e0..e4281caebe2452 100644 --- a/src/ui/ui_exports/ui_export_types/reduce/lib/index.js +++ b/src/ui/ui_exports/ui_export_types/reduce/lib/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { flatConcat } from './flat_concat'; export { mergeWith } from './merge_with'; export { createTypeReducer } from './create_type_reducer'; diff --git a/src/ui/ui_exports/ui_export_types/reduce/lib/merge_with.js b/src/ui/ui_exports/ui_export_types/reduce/lib/merge_with.js index edeab703f70c58..e7a29a2abc989b 100644 --- a/src/ui/ui_exports/ui_export_types/reduce/lib/merge_with.js +++ b/src/ui/ui_exports/ui_export_types/reduce/lib/merge_with.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const uniqueConcat = (arrayA, arrayB) => arrayB.reduce((acc, key) => ( acc.includes(key) ? acc diff --git a/src/ui/ui_exports/ui_export_types/reduce/merge_at_type.js b/src/ui/ui_exports/ui_export_types/reduce/merge_at_type.js index e2b79837c25f32..e6adb441cae8ac 100644 --- a/src/ui/ui_exports/ui_export_types/reduce/merge_at_type.js +++ b/src/ui/ui_exports/ui_export_types/reduce/merge_at_type.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { createTypeReducer } from './lib'; export const mergeAtType = createTypeReducer((a, b) => ({ diff --git a/src/ui/ui_exports/ui_export_types/saved_object_mappings.js b/src/ui/ui_exports/ui_export_types/saved_object_mappings.js index 118e08824fd959..de3570ce2e864b 100644 --- a/src/ui/ui_exports/ui_export_types/saved_object_mappings.js +++ b/src/ui/ui_exports/ui_export_types/saved_object_mappings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { flatConcatAtType } from './reduce'; import { alias, mapSpec, wrap } from './modify_reduce'; diff --git a/src/ui/ui_exports/ui_export_types/ui_app_extensions.js b/src/ui/ui_exports/ui_export_types/ui_app_extensions.js index edfa103e264e84..9a962a8881e56a 100644 --- a/src/ui/ui_exports/ui_export_types/ui_app_extensions.js +++ b/src/ui/ui_exports/ui_export_types/ui_app_extensions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { flatConcatValuesAtType } from './reduce'; import { mapSpec, alias, wrap } from './modify_reduce'; @@ -20,6 +39,7 @@ export const visRequestHandlers = appExtension; export const visEditorTypes = appExtension; export const savedObjectTypes = appExtension; export const embeddableFactories = appExtension; +export const dashboardPanelActions = appExtension; export const fieldFormats = appExtension; export const fieldFormatEditors = appExtension; export const spyModes = appExtension; diff --git a/src/ui/ui_exports/ui_export_types/ui_apps.js b/src/ui/ui_exports/ui_export_types/ui_apps.js index dc28a9dbc94cc8..59d933c5a061dd 100644 --- a/src/ui/ui_exports/ui_export_types/ui_apps.js +++ b/src/ui/ui_exports/ui_export_types/ui_apps.js @@ -1,4 +1,21 @@ -import { uniq } from 'lodash'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ import { flatConcatAtType } from './reduce'; import { alias, mapSpec, wrap } from './modify_reduce'; @@ -16,13 +33,18 @@ function applySpecDefaults(spec, type, pluginSpec) { linkToLastSubUrl = true, listed = !hidden, url = `/app/${id}`, - uses = [], } = spec; if (spec.injectVars) { throw new Error(`[plugin:${pluginId}] uiExports.app.injectVars has been removed. Use server.injectUiAppVars('${id}', () => { ... })`); } + if (spec.uses) { + throw new Error( + `[plugin:${pluginId}] uiExports.app.uses has been removed. Import these uiExport types with "import 'uiExports/{type}'"` + ); + } + return { pluginId, id, @@ -35,11 +57,6 @@ function applySpecDefaults(spec, type, pluginSpec) { linkToLastSubUrl, listed, url, - uses: uniq([ - ...uses, - 'chromeNavControls', - 'hacks', - ]), }; } diff --git a/src/ui/ui_exports/ui_export_types/ui_i18n.js b/src/ui/ui_exports/ui_export_types/ui_i18n.js index c734562f7737d1..01c85b6883025b 100644 --- a/src/ui/ui_exports/ui_export_types/ui_i18n.js +++ b/src/ui/ui_exports/ui_export_types/ui_i18n.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { flatConcatAtType } from './reduce'; import { wrap, alias } from './modify_reduce'; diff --git a/src/ui/ui_exports/ui_export_types/ui_nav_links.js b/src/ui/ui_exports/ui_export_types/ui_nav_links.js index e17a1970c562e5..34aff7463a249e 100644 --- a/src/ui/ui_exports/ui_export_types/ui_nav_links.js +++ b/src/ui/ui_exports/ui_export_types/ui_nav_links.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { flatConcatAtType } from './reduce'; import { wrap, alias } from './modify_reduce'; diff --git a/src/ui/ui_exports/ui_export_types/ui_settings.js b/src/ui/ui_exports/ui_export_types/ui_settings.js index 024c53682a7a7a..8d88490579c21f 100644 --- a/src/ui/ui_exports/ui_export_types/ui_settings.js +++ b/src/ui/ui_exports/ui_export_types/ui_settings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { mergeAtType } from './reduce'; import { wrap, uniqueKeys } from './modify_reduce'; diff --git a/src/ui/ui_exports/ui_export_types/unknown.js b/src/ui/ui_exports/ui_export_types/unknown.js index 27b3430428d2a5..a12a514d2e6bf7 100644 --- a/src/ui/ui_exports/ui_export_types/unknown.js +++ b/src/ui/ui_exports/ui_export_types/unknown.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { flatConcatAtType } from './reduce'; import { wrap, alias, debug } from './modify_reduce'; diff --git a/src/ui/ui_exports/ui_export_types/webpack_customizations.js b/src/ui/ui_exports/ui_export_types/webpack_customizations.js index f90e1bbae3774d..fb89d50d98702b 100644 --- a/src/ui/ui_exports/ui_export_types/webpack_customizations.js +++ b/src/ui/ui_exports/ui_export_types/webpack_customizations.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { isAbsolute } from 'path'; import { escapeRegExp } from 'lodash'; diff --git a/src/ui/ui_exports/ui_exports_mixin.js b/src/ui/ui_exports/ui_exports_mixin.js index d36c8f96016f26..ea2a07f3b265e0 100644 --- a/src/ui/ui_exports/ui_exports_mixin.js +++ b/src/ui/ui_exports/ui_exports_mixin.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { collectUiExports } from './collect_ui_exports'; export function uiExportsMixin(kbnServer) { diff --git a/src/ui/ui_i18n/README.md b/src/ui/ui_i18n/README.md new file mode 100644 index 00000000000000..4aecb8f1f0346b --- /dev/null +++ b/src/ui/ui_i18n/README.md @@ -0,0 +1,348 @@ +# I18n + +Kibana relies on several UI frameworks (React and Angular) and +requires localization in different environments (browser and NodeJS). +Internationalization engine is framework agnostic and consumable in +all parts of Kibana (React, Angular and NodeJS). In order to simplify +internationalization in UI frameworks, the additional abstractions are +built around the I18n engine: `react-intl` for React and custom +components for Angular. [React-intl](https://github.com/yahoo/react-intl) +is built around [intl-messageformat](https://github.com/yahoo/intl-messageformat), +so both React and Angular frameworks use the same engine and the same +message syntax. + +## Localization files + +Localization files have [JSON5](https://github.com/json5/json5) format. + +The main benefits of using `JSON5`: + +- Objects may have a single trailing comma. +- Single and multi-line comments are allowed. +- Strings may span multiple lines by escaping new line characters. + +Short example: + +```js +{ + // comments + unquoted: 'and you can quote me on that', + singleQuotes: 'I can use "double quotes" here', + lineBreaks: "Wow! \ +No \\n's!", + hexadecimal: 0xdecaf, + leadingDecimalPoint: .8675309, andTrailing: 8675309., + positiveSign: +1, + trailingComma: 'in objects', andIn: ['arrays',], + "backwardsCompatible": "with JSON", +} +``` + +Using comments can help to understand which section of the application +the localization key is used for. Also `namespaces` +are used in order to simplify message location search. For example, if +we are going to translate the title of `/management/sections/objects/_objects.html` +file, we should use message path like this: `'MANAGEMENT.OBJECTS.TITLE'`. + +Each Kibana plugin has a separate folder with translation files located at +``` +{path/to/plugin}/translations/{locale}.json +``` + +where `locale` is [ISO 639 language code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes). + +For example: +``` +src/core_plugins/kibana/translations/fr.json +``` + +When a new translation file is added, you have to register this file into +`uiExports.translations` array of plugin constructor parameters. For example: +```js +export default function (kibana) { + return new kibana.Plugin({ + uiExports: { + translations: [ + resolve(__dirname, './translations/fr.json'), + ], + ... + }, + ... + }); +} +``` + +The engine uses a locale resolution process similar to that of the built-in +Intl APIs to determine which locale data to use based on the `accept-language` +http header. + +The following are the abstract steps i18n engine goes through to resolve the locale value: + +- If there's data for the specified locale (localization file is registered in + `uiExports.translations`), then that locale will be resolved. +- If locale data is missing for a leaf locale like `fr-FR`, but there is data +for one of its ancestors, `fr` in this case, then its ancestor will be used. +- If `accept-language` header is not presented or previous steps didn't resolve +the locale, the locale will be resolved to locale defined in `i18n.defaultLocale` +option at `config/kibana.yml` file. + +One of our technical requirements is to have default message in the templates +themselves, and that message will always be english, so we don't need interact +with `en.json` file directly. We can generate that file from `defaultMessage`s +defined inline. + +## I18n engine + +I18n engine is the platform agnostic abstraction that helps to supply locale +data to UI frameworks and provides methods for the direct translation. + +Here is the public API exposed by this engine: + +- `getMessages()` - returns messages for the current language +- `setLocale(locale: string)` - tells the engine which language to use by given +language key +- `getLocale()` - returns the current locale +- `setDefaultLocale(locale: string)` - tells the library which language to fallback +when missing translations +- `getDefaultLocale()` - returns the default locale +- `defineFormats(formats: object)` - supplies a set of options to the underlying formatter. +For the detailed explanation, see the section below +- `translate(id: string, [{values: object, defaultMessage: string}])` – translate message by id + +#### I18n engine internals + +The engine uses the ICU Message syntax and works for all CLDR languages which +have pluralization rules defined. It's built around `intl-messageformat` package +which exposes `IntlMessageFormat` class. Messages are provided into the constructor +as a string message, or a pre-parsed AST object. + +```js +import IntlMessageFormat from 'intl-messageformat'; + +const msg = new IntlMessageFormat(message, locales, [formats]); +``` + +The string `message` is parsed, then stored internally in a +compiled form that is optimized for the `format()` method to +produce the formatted string for displaying to the user. + +```js +const output = msg.format(values); +``` + +`formats` parameter in `IntlMessageFormat` constructor allows formatting numbers +and dates/times in messages using `Intl.NumberFormat` and `Intl.DateTimeFormat`, +respectively. + +```js +const msg = new IntlMessageFormat('The price is: {price, number, USD}', 'en-US', { + number: { + USD: { + style : 'currency', + currency: 'USD', + }, + }, +}); + +const output = msg.format({ price: 100 }); + +console.log(output); // => "The price is: $100.00" +``` + +In this example, we're defining a USD number format style which is passed to +the underlying `Intl.NumberFormat` instance as its options. +[Here](https://github.com/yahoo/intl-messageformat/blob/master/src/core.js#L62) +you can find default format options used as the prototype of the formats +provided to the constructor. + +Creating instances of `IntlMessageFormat` is expensive. +[Intl-format-cache](https://github.com/yahoo/intl-format-cache) +library is simply to make it easier to create a cache of format +instances of a particular type to aid in their reuse. Under the +hood, this package creates a cache key based on the arguments passed +to the memoized constructor. + +```js +import memoizeIntlConstructor from 'intl-format-cache'; + +const getMessageFormat = memoizeIntlConstructor(IntlMessageFormat); +``` + +## React + +[React-intl](https://github.com/yahoo/react-intl) library is used for internalization +React part of the application. It provides React components and an API to format +dates, numbers, and strings, including pluralization and handling translations. + +React Intl uses the provider pattern to scope an i18n context to a tree of components. +`IntlProvider` component is used to setup the i18n context for a tree. After that we +are able to use `FormattedMessage` component in order to translate messages. +`IntlProvider` should wrap react app's root component (inside each react render method). + +In order to translate messages we need to pass them into the `IntlProvider` +from I18n engine: + +```js +import React from 'react'; +import ReactDOM from 'react-dom'; + +import i18n from 'kbn-i18n'; +import { IntlProvider } from 'ui/i18n/react-intl'; + +const locale = i18n.getLocale(); +const messages = i18n.getMessages(); + +ReactDOM.render( + + + ... + + , + document.getElementById('container') +); +``` + +After that we can use `FormattedMessage` components inside `RootComponent`: +```js +import React, { Component } from 'react'; + +import { FormattedMessage } from 'ui/i18n/react-intl'; + +class RootComponent extends Component { + constructor(props) { + super(props); + + this.state = { + name: 'Eric', + unreadCount: 1000, + }; + } + + render() { + const { + name, + unreadCount, + } = this.state; + + return ( +

+ {name}, unreadCount}} + /> + ... +

+ ); + } +} +``` + +## Angular + +Angular wrapper has 4 entities: translation `provider`, `service`, `directive` +and `filter`. Both the directive and the filter use the translation `service` +with i18n engine under the hood. + +The translation `provider` is used for `service` configuration and +has the following methods: +- `addMessages(messages: Map, [locale: string])` - provides a way to register +translations with the library +- `setLocale(locale: string)` - tells the library which language to use by given +language key +- `getLocale()` - returns the current locale +- `setDefaultLocale(locale: string)` - tells the library which language to fallback +when missing translations +- `getDefaultLocale()` - returns the default locale +- `defineFormats(formats: object)` - supplies a set of options to the underlying formatter + +The translation `service` provides only one method: +- `translate(id: string, [{values: object, defaultMessage: string}])` – translate message by id + +The translation `filter` is used for attributes translation and has +the following syntax: +``` +{{'translationId' | i18n[:{ values: object, defaultMessage: string }]}} +``` + +Where: +- `translationId` - translation id to be translated +- `values` - values to pass into translation +- `defaultMessage` - will be used unless translation was successful (the final + fallback in english, will be used for generating `en.json`) + +The translation `directive` has the following syntax: +```html + +``` + +Where: +- `i18n-id` - translation id to be translated +- `i18n-values` - values to pass into translation +- `i18n-default-message` - will be used unless translation was successful + +In order to initialize the translation service, we need to pass locale and +localization messages from I18n engine into the `i18nProvider`: + +```js +import { uiModules } from 'ui/modules'; +import i18n from 'kbn-i18n'; + +uiModules.get('kibana').config(function (i18nProvider) { + i18nProvider.addMessages(i18n.getMessages()); + i18nProvider.setLocale(i18n.getLocale()); +}); +``` + +After that we can use i18n directive in Angular templates: +```html + +``` + +## Node.JS + +`Intl-messageformat` package assumes that the +[Intl](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) +global object exists in the runtime. `Intl` is present in all modern +browsers and Node.js 0.10+. In order to load i18n engine +in Node.js we should simply `import` this module (in Node.js, the +[data](https://github.com/yahoo/intl-messageformat/tree/master/dist/locale-data) +for all 200+ languages is loaded along with the library): + +```js +import i18n from 'kbn-i18n'; +``` + +After that we are able to use all methods exposed by the i18n engine +(see [I18n engine](#i18n-engine) section above for more details). + +## Build tools + +In order to simplify localization process, some build tools will be added: +- tool for verifying all translations have translatable strings +- tool for checking unused translation strings +- tool for extracting default messages from templates + +While `react-intl` has +[babel-plugin-react-intl](https://github.com/yahoo/babel-plugin-react-intl) +library which extracts string messages for translation, angular wrapper requires +own implementation of such tool. In order to extracrt translation keys from the +template, we have to parse it and create AST object. There is a +[babel-plugin-syntax-jsx](https://github.com/babel/babel/tree/master/packages/babel-plugin-syntax-jsx) +plugin which helps to parse JSX syntax and then create AST object. Unfortunately, +there are no babel plugins to parse angular templates. One of the solution can be internal +[`$parse.$$getAst`](https://github.com/angular/angular.js/blob/master/src/ng/parse.js#L1819) +angular method. diff --git a/src/ui/ui_i18n/__tests__/i18n.js b/src/ui/ui_i18n/__tests__/i18n.js index f6def026899009..7ab16fc04cecfa 100644 --- a/src/ui/ui_i18n/__tests__/i18n.js +++ b/src/ui/ui_i18n/__tests__/i18n.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import _ from 'lodash'; import { join } from 'path'; diff --git a/src/ui/ui_i18n/i18n.js b/src/ui/ui_i18n/i18n.js index f9c495790a8eb9..4f466c1a62ad8b 100644 --- a/src/ui/ui_i18n/i18n.js +++ b/src/ui/ui_i18n/i18n.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import path from 'path'; import Promise from 'bluebird'; import { readFile } from 'fs'; diff --git a/src/ui/ui_i18n/index.js b/src/ui/ui_i18n/index.js index 166b45aa99ae0a..a4b45b98753269 100644 --- a/src/ui/ui_i18n/index.js +++ b/src/ui/ui_i18n/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { I18n } from './i18n'; export { uiI18nMixin } from './ui_i18n_mixin'; diff --git a/src/ui/ui_i18n/ui_i18n_mixin.js b/src/ui/ui_i18n/ui_i18n_mixin.js index c11b4c765a494a..f0c9caab2cabc9 100644 --- a/src/ui/ui_i18n/ui_i18n_mixin.js +++ b/src/ui/ui_i18n/ui_i18n_mixin.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { defaults, compact } from 'lodash'; import langParser from 'accept-language-parser'; diff --git a/src/ui/ui_mixin.js b/src/ui/ui_mixin.js index 01770061a26bc4..8015a44b1cad42 100644 --- a/src/ui/ui_mixin.js +++ b/src/ui/ui_mixin.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiExportsMixin } from './ui_exports'; import { fieldFormatsMixin } from './field_formats'; import { tutorialsMixin } from './tutorials_mixin'; diff --git a/src/ui/ui_nav_links/__tests__/ui_nav_link.js b/src/ui/ui_nav_links/__tests__/ui_nav_link.js index ee3a8c6c977c96..0cac7634731469 100644 --- a/src/ui/ui_nav_links/__tests__/ui_nav_link.js +++ b/src/ui/ui_nav_links/__tests__/ui_nav_link.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { UiNavLink } from '../ui_nav_link'; diff --git a/src/ui/ui_nav_links/index.js b/src/ui/ui_nav_links/index.js index 14968e51cda4ec..42cea918a6afc2 100644 --- a/src/ui/ui_nav_links/index.js +++ b/src/ui/ui_nav_links/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { UiNavLink } from './ui_nav_link'; export { uiNavLinksMixin } from './ui_nav_links_mixin'; diff --git a/src/ui/ui_nav_links/ui_nav_link.js b/src/ui/ui_nav_links/ui_nav_link.js index 322717c446d96f..8ecf6b2cb67825 100644 --- a/src/ui/ui_nav_links/ui_nav_link.js +++ b/src/ui/ui_nav_links/ui_nav_link.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export class UiNavLink { constructor(urlBasePath, spec) { const { diff --git a/src/ui/ui_nav_links/ui_nav_links_mixin.js b/src/ui/ui_nav_links/ui_nav_links_mixin.js index 38411c799bf348..2c94135a113e77 100644 --- a/src/ui/ui_nav_links/ui_nav_links_mixin.js +++ b/src/ui/ui_nav_links/ui_nav_links_mixin.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { UiNavLink } from './ui_nav_link'; export function uiNavLinksMixin(kbnServer, server, config) { diff --git a/src/ui/ui_render/bootstrap/app_bootstrap.js b/src/ui/ui_render/bootstrap/app_bootstrap.js index c0e797f36fbb96..f21aa3eda2279e 100644 --- a/src/ui/ui_render/bootstrap/app_bootstrap.js +++ b/src/ui/ui_render/bootstrap/app_bootstrap.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import Handlebars from 'handlebars'; import { createHash } from 'crypto'; diff --git a/src/ui/ui_render/bootstrap/app_bootstrap.test.js b/src/ui/ui_render/bootstrap/app_bootstrap.test.js index c30f6bb2808c08..3658cd1f35aa7a 100644 --- a/src/ui/ui_render/bootstrap/app_bootstrap.test.js +++ b/src/ui/ui_render/bootstrap/app_bootstrap.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import mockFs from 'mock-fs'; import { resolve } from 'path'; diff --git a/src/ui/ui_render/bootstrap/index.js b/src/ui/ui_render/bootstrap/index.js index e13babaacc4489..8fb188a9f64b5d 100644 --- a/src/ui/ui_render/bootstrap/index.js +++ b/src/ui/ui_render/bootstrap/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { AppBootstrap } from './app_bootstrap'; diff --git a/src/ui/ui_render/index.js b/src/ui/ui_render/index.js index 79bd880c2499dc..0905daf818ff6a 100644 --- a/src/ui/ui_render/index.js +++ b/src/ui/ui_render/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { uiRenderMixin } from './ui_render_mixin'; diff --git a/src/ui/ui_render/ui_render_mixin.js b/src/ui/ui_render/ui_render_mixin.js index 6387177ed7c5ac..66545c90209cb1 100644 --- a/src/ui/ui_render/ui_render_mixin.js +++ b/src/ui/ui_render/ui_render_mixin.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { defaults, get } from 'lodash'; import { props, reduce as reduceAsync } from 'bluebird'; import Boom from 'boom'; diff --git a/src/ui/ui_settings/__tests__/lib/create_objects_client_stub.js b/src/ui/ui_settings/__tests__/lib/create_objects_client_stub.js index 7c5a24d2fd3572..e5a638490b324a 100644 --- a/src/ui/ui_settings/__tests__/lib/create_objects_client_stub.js +++ b/src/ui/ui_settings/__tests__/lib/create_objects_client_stub.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; import { SavedObjectsClient } from '../../../../server/saved_objects/client'; diff --git a/src/ui/ui_settings/__tests__/lib/index.js b/src/ui/ui_settings/__tests__/lib/index.js index 0ca35ea49fb7da..29b1adbcba5760 100644 --- a/src/ui/ui_settings/__tests__/lib/index.js +++ b/src/ui/ui_settings/__tests__/lib/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { createObjectsClientStub, savedObjectsClientErrors, diff --git a/src/ui/ui_settings/__tests__/ui_settings_mixin_integration.js b/src/ui/ui_settings/__tests__/ui_settings_mixin_integration.js index b35caa0e3a73d5..44d633b0693957 100644 --- a/src/ui/ui_settings/__tests__/ui_settings_mixin_integration.js +++ b/src/ui/ui_settings/__tests__/ui_settings_mixin_integration.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; @@ -13,14 +32,14 @@ import { getUiSettingsServiceForRequest } from '../ui_settings_service_for_reque import { uiSettingsMixin } from '../ui_settings_mixin'; describe('uiSettingsMixin()', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); - function setup(options = {}) { + async function setup(options = {}) { const { enabled = true } = options; - const config = Config.withDefaultSchema({ + const config = await Config.withDefaultSchema({ uiSettings: { enabled } }); @@ -70,8 +89,8 @@ describe('uiSettingsMixin()', () => { afterEach(() => sandbox.restore()); describe('server.uiSettingsServiceFactory()', () => { - it('decorates server with "uiSettingsServiceFactory"', () => { - const { decorations } = setup(); + it('decorates server with "uiSettingsServiceFactory"', async () => { + const { decorations } = await setup(); expect(decorations.server).to.have.property('uiSettingsServiceFactory').a('function'); sandbox.stub(uiSettingsServiceFactoryNS, 'uiSettingsServiceFactory'); @@ -80,8 +99,8 @@ describe('uiSettingsMixin()', () => { sinon.assert.calledOnce(uiSettingsServiceFactory); }); - it('passes `server` and `options` argument to factory', () => { - const { decorations, server } = setup(); + it('passes `server` and `options` argument to factory', async () => { + const { decorations, server } = await setup(); expect(decorations.server).to.have.property('uiSettingsServiceFactory').a('function'); sandbox.stub(uiSettingsServiceFactoryNS, 'uiSettingsServiceFactory'); @@ -98,8 +117,8 @@ describe('uiSettingsMixin()', () => { }); describe('request.getUiSettingsService()', () => { - it('exposes "getUiSettingsService" on requests', () => { - const { decorations } = setup(); + it('exposes "getUiSettingsService" on requests', async () => { + const { decorations } = await setup(); expect(decorations.request).to.have.property('getUiSettingsService').a('function'); sandbox.stub(getUiSettingsServiceForRequestNS, 'getUiSettingsServiceForRequest'); @@ -108,8 +127,8 @@ describe('uiSettingsMixin()', () => { sinon.assert.calledOnce(getUiSettingsServiceForRequest); }); - it('passes request to getUiSettingsServiceForRequest', () => { - const { server, decorations } = setup(); + it('passes request to getUiSettingsServiceForRequest', async () => { + const { server, decorations } = await setup(); expect(decorations.request).to.have.property('getUiSettingsService').a('function'); sandbox.stub(getUiSettingsServiceForRequestNS, 'getUiSettingsServiceForRequest'); @@ -121,8 +140,8 @@ describe('uiSettingsMixin()', () => { }); describe('server.uiSettings()', () => { - it('throws an error, links to pr', () => { - const { decorations } = setup(); + it('throws an error, links to pr', async () => { + const { decorations } = await setup(); expect(decorations.server).to.have.property('uiSettings').a('function'); expect(() => { decorations.server.uiSettings(); diff --git a/src/ui/ui_settings/__tests__/ui_settings_service.js b/src/ui/ui_settings/__tests__/ui_settings_service.js index 2eb4bf1f259979..46757dc690baf7 100644 --- a/src/ui/ui_settings/__tests__/ui_settings_service.js +++ b/src/ui/ui_settings/__tests__/ui_settings_service.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { isEqual } from 'lodash'; import expect from 'expect.js'; import { errors as esErrors } from 'elasticsearch'; @@ -17,7 +36,7 @@ const BUILD_NUM = 1234; const chance = new Chance(); describe('ui settings', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); function setup(options = {}) { const { diff --git a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js index 9b5bb95c747620..316964875c6084 100644 --- a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js +++ b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_integration.js @@ -1,7 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; -import { createTestCluster } from '../../../../test_utils/es'; +import { createEsTestCluster } from '@kbn/test'; import { createServerWithCorePlugins } from '../../../../test_utils/kbn_server'; import { createToolingLog } from '@kbn/dev-utils'; import { createOrUpgradeSavedConfig } from '../create_or_upgrade_saved_config'; @@ -19,7 +38,7 @@ describe('createOrUpgradeSavedConfig()', () => { log.info('starting elasticsearch'); log.indent(4); - const es = createTestCluster({ log }); + const es = createEsTestCluster({ log }); this.timeout(es.getStartTimeout()); log.indent(-4); @@ -47,7 +66,7 @@ describe('createOrUpgradeSavedConfig()', () => { type: 'config', attributes: { buildNum: 54090, - '5.4.0-SNAPSHOT': true + '5.4.0-SNAPSHOT': true, }, }, { @@ -55,7 +74,7 @@ describe('createOrUpgradeSavedConfig()', () => { type: 'config', attributes: { buildNum: 54010, - '5.4.0-rc1': true + '5.4.0-rc1': true, }, }, { @@ -63,7 +82,7 @@ describe('createOrUpgradeSavedConfig()', () => { type: 'config', attributes: { buildNum: 99999, - '@@version': true + '@@version': true, }, }, ]); @@ -83,18 +102,20 @@ describe('createOrUpgradeSavedConfig()', () => { savedObjectsClient, version: '5.4.0', buildNum: 54099, - log: sinon.stub() + log: sinon.stub(), }); const config540 = await savedObjectsClient.get('config', '5.4.0'); - expect(config540).to.have.property('attributes').eql({ - // should have the new build number - buildNum: 54099, + expect(config540) + .to.have.property('attributes') + .eql({ + // should have the new build number + buildNum: 54099, - // 5.4.0-SNAPSHOT and @@version were ignored so we only have the - // attributes from 5.4.0-rc1, even though the other build nums are greater - '5.4.0-rc1': true, - }); + // 5.4.0-SNAPSHOT and @@version were ignored so we only have the + // attributes from 5.4.0-rc1, even though the other build nums are greater + '5.4.0-rc1': true, + }); // add the 5.4.0 flag to the 5.4.0 savedConfig await savedObjectsClient.update('config', '5.4.0', { @@ -107,18 +128,20 @@ describe('createOrUpgradeSavedConfig()', () => { savedObjectsClient, version: '5.4.1', buildNum: 54199, - log: sinon.stub() + log: sinon.stub(), }); const config541 = await savedObjectsClient.get('config', '5.4.1'); - expect(config541).to.have.property('attributes').eql({ - // should have the new build number - buildNum: 54199, + expect(config541) + .to.have.property('attributes') + .eql({ + // should have the new build number + buildNum: 54199, - // should also include properties from 5.4.0 and 5.4.0-rc1 - '5.4.0': true, - '5.4.0-rc1': true, - }); + // should also include properties from 5.4.0 and 5.4.0-rc1 + '5.4.0': true, + '5.4.0-rc1': true, + }); // add the 5.4.1 flag to the 5.4.1 savedConfig await savedObjectsClient.update('config', '5.4.1', { @@ -131,19 +154,21 @@ describe('createOrUpgradeSavedConfig()', () => { savedObjectsClient, version: '7.0.0-rc1', buildNum: 70010, - log: sinon.stub() + log: sinon.stub(), }); const config700rc1 = await savedObjectsClient.get('config', '7.0.0-rc1'); - expect(config700rc1).to.have.property('attributes').eql({ - // should have the new build number - buildNum: 70010, - - // should also include properties from 5.4.1, 5.4.0 and 5.4.0-rc1 - '5.4.1': true, - '5.4.0': true, - '5.4.0-rc1': true, - }); + expect(config700rc1) + .to.have.property('attributes') + .eql({ + // should have the new build number + buildNum: 70010, + + // should also include properties from 5.4.1, 5.4.0 and 5.4.0-rc1 + '5.4.1': true, + '5.4.0': true, + '5.4.0-rc1': true, + }); // tag the 7.0.0-rc1 doc await savedObjectsClient.update('config', '7.0.0-rc1', { @@ -156,20 +181,22 @@ describe('createOrUpgradeSavedConfig()', () => { savedObjectsClient, version: '7.0.0', buildNum: 70099, - log: sinon.stub() + log: sinon.stub(), }); const config700 = await savedObjectsClient.get('config', '7.0.0'); - expect(config700).to.have.property('attributes').eql({ - // should have the new build number - buildNum: 70099, - - // should also include properties from ancestors, including 7.0.0-rc1 - '7.0.0-rc1': true, - '5.4.1': true, - '5.4.0': true, - '5.4.0-rc1': true, - }); + expect(config700) + .to.have.property('attributes') + .eql({ + // should have the new build number + buildNum: 70099, + + // should also include properties from ancestors, including 7.0.0-rc1 + '7.0.0-rc1': true, + '5.4.1': true, + '5.4.0': true, + '5.4.0-rc1': true, + }); // tag the 7.0.0 doc await savedObjectsClient.update('config', '7.0.0', { @@ -182,18 +209,20 @@ describe('createOrUpgradeSavedConfig()', () => { savedObjectsClient, version: '6.2.3-rc1', buildNum: 62310, - log: sinon.stub() + log: sinon.stub(), }); const config623rc1 = await savedObjectsClient.get('config', '6.2.3-rc1'); - expect(config623rc1).to.have.property('attributes').eql({ - // should have the new build number - buildNum: 62310, - - // should also include properties from ancestors, but not 7.0.0-rc1 or 7.0.0 - '5.4.1': true, - '5.4.0': true, - '5.4.0-rc1': true, - }); + expect(config623rc1) + .to.have.property('attributes') + .eql({ + // should have the new build number + buildNum: 62310, + + // should also include properties from ancestors, but not 7.0.0-rc1 or 7.0.0 + '5.4.1': true, + '5.4.0': true, + '5.4.0-rc1': true, + }); }); }); diff --git a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js index 6fd8d5fc169c62..e25002e9c9c1c1 100644 --- a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js +++ b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import Chance from 'chance'; @@ -7,7 +26,7 @@ import { createOrUpgradeSavedConfig } from '../create_or_upgrade_saved_config'; const chance = new Chance(); describe('uiSettings/createOrUpgradeSavedConfig', function () { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); afterEach(() => sandbox.restore()); const version = '4.0.1'; diff --git a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/is_config_version_upgradeable.js b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/is_config_version_upgradeable.js index 5c05ed527a17d7..caadaf1d4eedc6 100644 --- a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/is_config_version_upgradeable.js +++ b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/is_config_version_upgradeable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { isConfigVersionUpgradeable } from '../is_config_version_upgradeable'; diff --git a/src/ui/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.js b/src/ui/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.js index f483d001bd3b7b..bf3a49fcbdc3ea 100644 --- a/src/ui/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.js +++ b/src/ui/ui_settings/create_or_upgrade_saved_config/create_or_upgrade_saved_config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { defaults } from 'lodash'; import { getUpgradeableConfig } from './get_upgradeable_config'; diff --git a/src/ui/ui_settings/create_or_upgrade_saved_config/get_upgradeable_config.js b/src/ui/ui_settings/create_or_upgrade_saved_config/get_upgradeable_config.js index 2d8729209023b7..1108a011675809 100644 --- a/src/ui/ui_settings/create_or_upgrade_saved_config/get_upgradeable_config.js +++ b/src/ui/ui_settings/create_or_upgrade_saved_config/get_upgradeable_config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { isConfigVersionUpgradeable } from './is_config_version_upgradeable'; /** diff --git a/src/ui/ui_settings/create_or_upgrade_saved_config/index.js b/src/ui/ui_settings/create_or_upgrade_saved_config/index.js index 5cb1112e41e2f8..839bcf8d4d7fd4 100644 --- a/src/ui/ui_settings/create_or_upgrade_saved_config/index.js +++ b/src/ui/ui_settings/create_or_upgrade_saved_config/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { createOrUpgradeSavedConfig } from './create_or_upgrade_saved_config'; diff --git a/src/ui/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.js b/src/ui/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.js index 4b3219a794c500..beeba6717f24a1 100644 --- a/src/ui/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.js +++ b/src/ui/ui_settings/create_or_upgrade_saved_config/is_config_version_upgradeable.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import semver from 'semver'; const rcVersionRegex = /^(\d+\.\d+\.\d+)\-rc(\d+)$/i; diff --git a/src/ui/ui_settings/index.js b/src/ui/ui_settings/index.js index 5f74d8bdef5b5c..ec3122c4e390ef 100644 --- a/src/ui/ui_settings/index.js +++ b/src/ui/ui_settings/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { uiSettingsMixin } from './ui_settings_mixin'; diff --git a/src/ui/ui_settings/public/send_request.js b/src/ui/ui_settings/public/send_request.js index 1199707423ba39..3f138fe0373c87 100644 --- a/src/ui/ui_settings/public/send_request.js +++ b/src/ui/ui_settings/public/send_request.js @@ -1,20 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import chrome from 'ui/chrome'; +import { metadata } from 'ui/metadata'; export async function sendRequest({ method, path, body }) { - const response = await fetch(chrome.addBasePath(path), { - method, - body: JSON.stringify(body), - headers: { - accept: 'application/json', - 'content-type': 'application/json', - 'kbn-xsrf': 'kibana', - }, - credentials: 'same-origin' - }); + chrome.loadingCount.increment(); + try { + const response = await fetch(chrome.addBasePath(path), { + method, + body: JSON.stringify(body), + headers: { + accept: 'application/json', + 'content-type': 'application/json', + 'kbn-version': metadata.version, + }, + credentials: 'same-origin' + }); - if (response.status >= 300) { - throw new Error(`Request failed with status code: ${response.status}`); - } + if (response.status >= 300) { + throw new Error(`Request failed with status code: ${response.status}`); + } - return await response.json(); + return await response.json(); + } finally { + chrome.loadingCount.decrement(); + } } diff --git a/src/ui/ui_settings/public/ui_settings_api.js b/src/ui/ui_settings/public/ui_settings_api.js index 7ccb7aabb4211a..efa667d30af2d1 100644 --- a/src/ui/ui_settings/public/ui_settings_api.js +++ b/src/ui/ui_settings/public/ui_settings_api.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { sendRequest } from './send_request'; const NOOP_CHANGES = { diff --git a/src/ui/ui_settings/public/ui_settings_api.test.js b/src/ui/ui_settings/public/ui_settings_api.test.js index 73a4c7e2816885..053a4eedde34cf 100644 --- a/src/ui/ui_settings/public/ui_settings_api.test.js +++ b/src/ui/ui_settings/public/ui_settings_api.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { createUiSettingsApi } from './ui_settings_api'; import { sendRequest } from './send_request'; diff --git a/src/ui/ui_settings/public/ui_settings_client.js b/src/ui/ui_settings/public/ui_settings_client.js index 90b1db11445079..1f725520f26de9 100644 --- a/src/ui/ui_settings/public/ui_settings_client.js +++ b/src/ui/ui_settings/public/ui_settings_client.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { cloneDeep, defaultsDeep } from 'lodash'; import { createUiSettingsApi } from './ui_settings_api'; diff --git a/src/ui/ui_settings/public/ui_settings_client.test.js b/src/ui/ui_settings/public/ui_settings_client.test.js index b557d5a2c66cee..f06baea81c251e 100644 --- a/src/ui/ui_settings/public/ui_settings_client.test.js +++ b/src/ui/ui_settings/public/ui_settings_client.test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { UiSettingsClient } from './ui_settings_client'; import { sendRequest } from './send_request'; diff --git a/src/ui/ui_settings/routes/__tests__/doc_exists.js b/src/ui/ui_settings/routes/__tests__/doc_exists.js index 4a1ad6fb629a05..7cc1f8b5423541 100644 --- a/src/ui/ui_settings/routes/__tests__/doc_exists.js +++ b/src/ui/ui_settings/routes/__tests__/doc_exists.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import sinon from 'sinon'; diff --git a/src/ui/ui_settings/routes/__tests__/doc_missing.js b/src/ui/ui_settings/routes/__tests__/doc_missing.js index a1aa547d9e2f0a..4fd39649a50049 100644 --- a/src/ui/ui_settings/routes/__tests__/doc_missing.js +++ b/src/ui/ui_settings/routes/__tests__/doc_missing.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import sinon from 'sinon'; diff --git a/src/ui/ui_settings/routes/__tests__/index.js b/src/ui/ui_settings/routes/__tests__/index.js index 0f5c4eb3ccdaeb..ca4a9e589de9b1 100644 --- a/src/ui/ui_settings/routes/__tests__/index.js +++ b/src/ui/ui_settings/routes/__tests__/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { startServers, stopServers, diff --git a/src/ui/ui_settings/routes/__tests__/index_missing.js b/src/ui/ui_settings/routes/__tests__/index_missing.js index 994d70c6575281..838cc9b48b5245 100644 --- a/src/ui/ui_settings/routes/__tests__/index_missing.js +++ b/src/ui/ui_settings/routes/__tests__/index_missing.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import sinon from 'sinon'; diff --git a/src/ui/ui_settings/routes/__tests__/lib/assert.js b/src/ui/ui_settings/routes/__tests__/lib/assert.js index 846c8b77082672..c7b8e057092643 100644 --- a/src/ui/ui_settings/routes/__tests__/lib/assert.js +++ b/src/ui/ui_settings/routes/__tests__/lib/assert.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; export function assertSinonMatch(value, match) { diff --git a/src/ui/ui_settings/routes/__tests__/lib/chance.js b/src/ui/ui_settings/routes/__tests__/lib/chance.js index f3b9840f575379..90ac6190129263 100644 --- a/src/ui/ui_settings/routes/__tests__/lib/chance.js +++ b/src/ui/ui_settings/routes/__tests__/lib/chance.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Chance from 'chance'; export const chance = new Chance(); diff --git a/src/ui/ui_settings/routes/__tests__/lib/index.js b/src/ui/ui_settings/routes/__tests__/lib/index.js index 7cdb162c83a965..ecc20a09149d30 100644 --- a/src/ui/ui_settings/routes/__tests__/lib/index.js +++ b/src/ui/ui_settings/routes/__tests__/lib/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { startServers, getServices, diff --git a/src/ui/ui_settings/routes/__tests__/lib/servers.js b/src/ui/ui_settings/routes/__tests__/lib/servers.js index 773dbba9016bd3..1b65f10d489203 100644 --- a/src/ui/ui_settings/routes/__tests__/lib/servers.js +++ b/src/ui/ui_settings/routes/__tests__/lib/servers.js @@ -1,4 +1,24 @@ -import { createTestCluster } from '../../../../../test_utils/es'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createEsTestCluster } from '@kbn/test'; +import { createToolingLog } from '@kbn/dev-utils'; import * as kbnTestServer from '../../../../../test_utils/kbn_server'; let kbnServer; @@ -6,9 +26,17 @@ let services; let es; export async function startServers() { - es = createTestCluster(); + const log = createToolingLog('debug'); + log.pipe(process.stdout); + log.indent(6); + + log.info('starting elasticsearch'); + log.indent(4); + + es = createEsTestCluster({ log }); this.timeout(es.getStartTimeout()); + log.indent(-4); await es.start(); kbnServer = kbnTestServer.createServerWithCorePlugins(); @@ -35,7 +63,7 @@ export function getServices() { kbnServer, callCluster, savedObjectsClient, - uiSettings + uiSettings, }; return services; diff --git a/src/ui/ui_settings/routes/delete.js b/src/ui/ui_settings/routes/delete.js index ccd3418101b52f..4fee12afd8081a 100644 --- a/src/ui/ui_settings/routes/delete.js +++ b/src/ui/ui_settings/routes/delete.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + async function handleRequest(request) { const { key } = request.params; const uiSettings = request.getUiSettingsService(); diff --git a/src/ui/ui_settings/routes/get.js b/src/ui/ui_settings/routes/get.js index 813c6b8a1fe2df..9f6c99acbd8cfb 100644 --- a/src/ui/ui_settings/routes/get.js +++ b/src/ui/ui_settings/routes/get.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + async function handleRequest(request) { const uiSettings = request.getUiSettingsService(); return { diff --git a/src/ui/ui_settings/routes/index.js b/src/ui/ui_settings/routes/index.js index 9100e0107ac35d..f3c9d4f0d8d14f 100644 --- a/src/ui/ui_settings/routes/index.js +++ b/src/ui/ui_settings/routes/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { deleteRoute } from './delete'; export { getRoute } from './get'; export { setManyRoute } from './set_many'; diff --git a/src/ui/ui_settings/routes/set.js b/src/ui/ui_settings/routes/set.js index 1f7e2faa4f0afc..54be14584f1d2d 100644 --- a/src/ui/ui_settings/routes/set.js +++ b/src/ui/ui_settings/routes/set.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Joi from 'joi'; async function handleRequest(request) { diff --git a/src/ui/ui_settings/routes/set_many.js b/src/ui/ui_settings/routes/set_many.js index 95af422ac194fc..d215b5f1a717d9 100644 --- a/src/ui/ui_settings/routes/set_many.js +++ b/src/ui/ui_settings/routes/set_many.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Joi from 'joi'; async function handleRequest(request) { diff --git a/src/ui/ui_settings/ui_exports_consumer.js b/src/ui/ui_settings/ui_exports_consumer.js index 74962c88450493..d2bb3a00ce0ede 100644 --- a/src/ui/ui_settings/ui_exports_consumer.js +++ b/src/ui/ui_settings/ui_exports_consumer.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * The UiExports class accepts consumer objects that it consults while * trying to consume all of the `uiExport` declarations provided by diff --git a/src/ui/ui_settings/ui_settings_mixin.js b/src/ui/ui_settings/ui_settings_mixin.js index 1ba6ce614793e9..6ea81df2c229b6 100644 --- a/src/ui/ui_settings/ui_settings_mixin.js +++ b/src/ui/ui_settings/ui_settings_mixin.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiSettingsServiceFactory } from './ui_settings_service_factory'; import { getUiSettingsServiceForRequest } from './ui_settings_service_for_request'; import { diff --git a/src/ui/ui_settings/ui_settings_service.js b/src/ui/ui_settings/ui_settings_service.js index e2ffe2cd7e31e1..bf9b12133999ac 100644 --- a/src/ui/ui_settings/ui_settings_service.js +++ b/src/ui/ui_settings/ui_settings_service.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { defaultsDeep } from 'lodash'; import { createOrUpgradeSavedConfig } from './create_or_upgrade_saved_config'; diff --git a/src/ui/ui_settings/ui_settings_service_factory.js b/src/ui/ui_settings/ui_settings_service_factory.js index 5965b8d40800c4..4b9859abf6bdb3 100644 --- a/src/ui/ui_settings/ui_settings_service_factory.js +++ b/src/ui/ui_settings/ui_settings_service_factory.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { UiSettingsService } from './ui_settings_service'; /** diff --git a/src/ui/ui_settings/ui_settings_service_for_request.js b/src/ui/ui_settings/ui_settings_service_for_request.js index 484a0aecf68707..58dcbe22b4b0c5 100644 --- a/src/ui/ui_settings/ui_settings_service_for_request.js +++ b/src/ui/ui_settings/ui_settings_service_for_request.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { uiSettingsServiceFactory } from './ui_settings_service_factory'; /** diff --git a/src/utils/__tests__/case_conversion.js b/src/utils/__tests__/case_conversion.js index b7894126c5a5bc..03b1f7c58644a7 100644 --- a/src/utils/__tests__/case_conversion.js +++ b/src/utils/__tests__/case_conversion.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import _ from 'lodash'; import { keysToSnakeCaseShallow, keysToCamelCaseShallow } from '../case_conversion'; diff --git a/src/utils/__tests__/deep_clone_with_buffers.js b/src/utils/__tests__/deep_clone_with_buffers.js index 90b75de1864a9a..c1d976e8fc237c 100644 --- a/src/utils/__tests__/deep_clone_with_buffers.js +++ b/src/utils/__tests__/deep_clone_with_buffers.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { deepCloneWithBuffers } from '../deep_clone_with_buffers'; import expect from 'expect.js'; diff --git a/src/utils/__tests__/fixtures/log_on_sigint.js b/src/utils/__tests__/fixtures/log_on_sigint.js new file mode 100644 index 00000000000000..810b0e07fb3c81 --- /dev/null +++ b/src/utils/__tests__/fixtures/log_on_sigint.js @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +console.log('listening for SIGINT'); +setTimeout(() => { + console.log('SIGINT not received'); +}, 10000); diff --git a/src/utils/__tests__/get_flattened_object.js b/src/utils/__tests__/get_flattened_object.js index e51615593bffcb..db4e48d93de7fb 100644 --- a/src/utils/__tests__/get_flattened_object.js +++ b/src/utils/__tests__/get_flattened_object.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { getFlattenedObject } from '../get_flattened_object'; diff --git a/src/utils/__tests__/kbn_field_types.js b/src/utils/__tests__/kbn_field_types.js index ad71a3eebc3f1c..c703d14749d54a 100644 --- a/src/utils/__tests__/kbn_field_types.js +++ b/src/utils/__tests__/kbn_field_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import Chance from 'chance'; diff --git a/src/utils/__tests__/modify_url.js b/src/utils/__tests__/modify_url.js index 3c468cd30fe2b8..9aa7ba1fb99601 100644 --- a/src/utils/__tests__/modify_url.js +++ b/src/utils/__tests__/modify_url.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { modifyUrl } from '../modify_url'; diff --git a/src/utils/__tests__/unset.js b/src/utils/__tests__/unset.js index 4f2fbb1efaa685..5540c2cc23aebd 100644 --- a/src/utils/__tests__/unset.js +++ b/src/utils/__tests__/unset.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { unset } from '../unset'; import expect from 'expect.js'; diff --git a/src/utils/__tests__/watch_stdio_for_line.js b/src/utils/__tests__/watch_stdio_for_line.js new file mode 100644 index 00000000000000..89d873792d9b6f --- /dev/null +++ b/src/utils/__tests__/watch_stdio_for_line.js @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import execa from 'execa'; +import stripAnsi from 'strip-ansi'; +import sinon from 'sinon'; + +import { watchStdioForLine } from '../watch_stdio_for_line'; + +describe('src/utils/watch_stdio_for_line', function () { + const sandbox = sinon.sandbox.create(); + afterEach(() => sandbox.reset()); + + const onLogLine = sandbox.stub(); + const logFn = line => onLogLine(stripAnsi(line)); + + it('calls logFn with log lines', async () => { + const proc = execa(process.execPath, ['-e', 'console.log("hi")']); + + await watchStdioForLine(proc, logFn); + + // log output of the process + sinon.assert.calledWithExactly(onLogLine, sinon.match(/hi/)); + }); + + it('send the proc SIGKILL if it logs a line matching exitAfter regexp', async function () { + // fixture proc will exit after 10 seconds if sigint not received, but the test won't fail + // unless we see the log line `SIGINT not received`, so we let the test take up to 30 seconds + // for potentially huge delays here and there + this.timeout(30000); + + const proc = execa(process.execPath, [require.resolve('./fixtures/log_on_sigint')]); + + await watchStdioForLine(proc, logFn, /listening for SIGINT/); + + sinon.assert.calledWithExactly(onLogLine, sinon.match(/listening for SIGINT/)); + sinon.assert.neverCalledWith(onLogLine, sinon.match(/SIGINT not received/)); + }); +}); diff --git a/src/utils/binder.js b/src/utils/binder.js index e82d6b7ecdf88f..6d1d3e62b0dcbf 100644 --- a/src/utils/binder.js +++ b/src/utils/binder.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export class BinderBase { constructor() { this.disposal = []; diff --git a/src/utils/binder_for.js b/src/utils/binder_for.js index 49b8452f5b032e..56b7d807358b52 100644 --- a/src/utils/binder_for.js +++ b/src/utils/binder_for.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { BinderBase } from './binder'; export class BinderFor extends BinderBase { diff --git a/src/utils/case_conversion.js b/src/utils/case_conversion.js index 765bb5e7ff553a..1d4fb7921ac750 100644 --- a/src/utils/case_conversion.js +++ b/src/utils/case_conversion.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; export function keysToSnakeCaseShallow(object) { diff --git a/src/utils/collection.js b/src/utils/collection.js index 35712beceeacd0..8c897b941dc3fa 100644 --- a/src/utils/collection.js +++ b/src/utils/collection.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const set = Symbol('internal set'); diff --git a/src/utils/deep_clone_with_buffers.js b/src/utils/deep_clone_with_buffers.js index 63161e5b1ba3a1..8f00ad752c19b8 100644 --- a/src/utils/deep_clone_with_buffers.js +++ b/src/utils/deep_clone_with_buffers.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { cloneDeep } from 'lodash'; function cloneBuffersCustomizer(val) { diff --git a/src/utils/encode_query_component.js b/src/utils/encode_query_component.js index ba77e3d8d1fe87..e8823beaa2b3eb 100644 --- a/src/utils/encode_query_component.js +++ b/src/utils/encode_query_component.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * This method is intended for encoding *key* or *value* parts of query component. We need a custom * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be diff --git a/src/utils/from_root.js b/src/utils/from_root.js index 1bb7ce0376fe51..2d85b8f1dab38d 100644 --- a/src/utils/from_root.js +++ b/src/utils/from_root.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { pkg } from './package_json'; import { resolve } from 'path'; diff --git a/src/utils/get_flattened_object.js b/src/utils/get_flattened_object.js index 7f5f9fe09ef33c..000fa0cdfabbd3 100644 --- a/src/utils/get_flattened_object.js +++ b/src/utils/get_flattened_object.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + function shouldReadKeys(value) { return typeof value === 'object' && value !== null && !Array.isArray(value); diff --git a/src/utils/index.js b/src/utils/index.js index 3eeaff00c6d4aa..18883e8f713592 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { BinderBase } from './binder'; export { BinderFor } from './binder_for'; export { deepCloneWithBuffers } from './deep_clone_with_buffers'; @@ -7,6 +26,7 @@ export { unset } from './unset'; export { encodeQueryComponent } from './encode_query_component'; export { modifyUrl } from './modify_url'; export { getFlattenedObject } from './get_flattened_object'; +export { watchStdioForLine } from './watch_stdio_for_line'; export { getKbnTypeNames, @@ -15,6 +35,7 @@ export { } from './kbn_field_types'; export { + concatStreamProviders, createConcatStream, createIntersperseStream, createJsonParseStream, diff --git a/src/utils/kbn_field_types.js b/src/utils/kbn_field_types.js index c83ea814ae4d1e..ddf14bb5162216 100644 --- a/src/utils/kbn_field_types.js +++ b/src/utils/kbn_field_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export class KbnFieldType { constructor(options = {}) { @@ -17,7 +36,7 @@ export class KbnFieldType { } } -const KBN_FIELD_TYPES = [ +export const KBN_FIELD_TYPES = [ new KbnFieldType({ name: 'string', sortable: true, diff --git a/src/utils/modify_url.js b/src/utils/modify_url.js index 97201813b36ec5..9fe4b644d612b5 100644 --- a/src/utils/modify_url.js +++ b/src/utils/modify_url.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { parse as parseUrl, format as formatUrl } from 'url'; /** diff --git a/src/utils/package_json.js b/src/utils/package_json.js index 9662f8e3fdd693..e8130345a6f9da 100644 --- a/src/utils/package_json.js +++ b/src/utils/package_json.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { dirname } from 'path'; export const pkg = { diff --git a/src/utils/path_contains.js b/src/utils/path_contains.js index 5c61fa28b75c77..60d05c10995542 100644 --- a/src/utils/path_contains.js +++ b/src/utils/path_contains.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { relative } from 'path'; export default function pathContains(root, child) { diff --git a/src/utils/streams/__tests__/concat_stream.js b/src/utils/streams/__tests__/concat_stream.js index 1741c2313fa34f..d26bd515dff299 100644 --- a/src/utils/streams/__tests__/concat_stream.js +++ b/src/utils/streams/__tests__/concat_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { diff --git a/src/utils/streams/__tests__/concat_stream_providers.js b/src/utils/streams/__tests__/concat_stream_providers.js new file mode 100644 index 00000000000000..b84732b17a5a87 --- /dev/null +++ b/src/utils/streams/__tests__/concat_stream_providers.js @@ -0,0 +1,79 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Readable } from 'stream'; + +import sinon from 'sinon'; +import expect from 'expect.js'; + +import { concatStreamProviders } from '../concat_stream_providers'; +import { createListStream } from '../list_stream'; +import { createConcatStream } from '../concat_stream'; +import { createPromiseFromStreams } from '../promise_from_streams'; + +describe('concatStreamProviders() helper', () => { + it('writes the data from an array of stream providers into a destination stream in order', async () => { + const results = await createPromiseFromStreams([ + concatStreamProviders([ + () => createListStream([ + 'foo', + 'bar' + ]), + () => createListStream([ + 'baz', + ]), + () => createListStream([ + 'bug', + ]), + ]), + createConcatStream('') + ]); + + expect(results).to.be('foobarbazbug'); + }); + + it('emits the errors from a sub-stream to the destination', async () => { + const dest = concatStreamProviders([ + () => createListStream([ + 'foo', + 'bar' + ]), + () => new Readable({ + read() { + this.emit('error', new Error('foo')); + } + }), + ]); + + const errorListener = sinon.stub(); + dest.on('error', errorListener); + + try { + await createPromiseFromStreams([dest]); + throw new Error('Expected createPromiseFromStreams() to reject with error'); + } catch (error) { + expect(error).to.have.property('message', 'foo'); + } + + sinon.assert.calledOnce(errorListener); + sinon.assert.calledWithExactly(errorListener, sinon.match({ + message: 'foo' + })); + }); +}); diff --git a/src/utils/streams/__tests__/intersperse_stream.js b/src/utils/streams/__tests__/intersperse_stream.js index f0638be121d8a1..fedf18e971e13e 100644 --- a/src/utils/streams/__tests__/intersperse_stream.js +++ b/src/utils/streams/__tests__/intersperse_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import sinon from 'sinon'; @@ -27,7 +46,7 @@ describe('intersperseStream', () => { str.write('a'); sinon.assert.calledOnce(stub); expect(stub.firstCall.args).to.eql(['a']); - stub.reset(); + stub.resetHistory(); str.write('b'); sinon.assert.calledTwice(stub); diff --git a/src/utils/streams/__tests__/json_parse_stream.js b/src/utils/streams/__tests__/json_parse_stream.js index 05a17239b33829..8e02593bc72b60 100644 --- a/src/utils/streams/__tests__/json_parse_stream.js +++ b/src/utils/streams/__tests__/json_parse_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { diff --git a/src/utils/streams/__tests__/json_stringify_stream.js b/src/utils/streams/__tests__/json_stringify_stream.js index 5f694567bbba4b..1eb178d4b7d15c 100644 --- a/src/utils/streams/__tests__/json_stringify_stream.js +++ b/src/utils/streams/__tests__/json_stringify_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { diff --git a/src/utils/streams/__tests__/list_stream.js b/src/utils/streams/__tests__/list_stream.js index 6fc8a85d871789..61c5eb2b02d4fc 100644 --- a/src/utils/streams/__tests__/list_stream.js +++ b/src/utils/streams/__tests__/list_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import sinon from 'sinon'; diff --git a/src/utils/streams/__tests__/map_stream.js b/src/utils/streams/__tests__/map_stream.js index 94d391826c920e..4e0f7103c62a90 100644 --- a/src/utils/streams/__tests__/map_stream.js +++ b/src/utils/streams/__tests__/map_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; import { delay } from 'bluebird'; diff --git a/src/utils/streams/__tests__/promise_from_streams.js b/src/utils/streams/__tests__/promise_from_streams.js index a0adda1b9d3734..d80bdad6e6fa62 100644 --- a/src/utils/streams/__tests__/promise_from_streams.js +++ b/src/utils/streams/__tests__/promise_from_streams.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Writable, Duplex } from 'stream'; import expect from 'expect.js'; diff --git a/src/utils/streams/__tests__/reduce_stream.js b/src/utils/streams/__tests__/reduce_stream.js index 1b237e84f40a92..e08d91cf0395b4 100644 --- a/src/utils/streams/__tests__/reduce_stream.js +++ b/src/utils/streams/__tests__/reduce_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import sinon from 'sinon'; import expect from 'expect.js'; diff --git a/src/utils/streams/__tests__/replace_stream.js b/src/utils/streams/__tests__/replace_stream.js index d2c1f70fa92cdf..baa939c50a6b1c 100644 --- a/src/utils/streams/__tests__/replace_stream.js +++ b/src/utils/streams/__tests__/replace_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { diff --git a/src/utils/streams/__tests__/split_stream.js b/src/utils/streams/__tests__/split_stream.js index 6f720458afc432..26beebe2ddd74c 100644 --- a/src/utils/streams/__tests__/split_stream.js +++ b/src/utils/streams/__tests__/split_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { diff --git a/src/utils/streams/concat_stream.js b/src/utils/streams/concat_stream.js index 4697f4062a8c01..89b0dff3b3d148 100644 --- a/src/utils/streams/concat_stream.js +++ b/src/utils/streams/concat_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { createReduceStream } from './reduce_stream'; /** diff --git a/src/utils/streams/concat_stream_providers.js b/src/utils/streams/concat_stream_providers.js new file mode 100644 index 00000000000000..adbbcf9a0d5f9d --- /dev/null +++ b/src/utils/streams/concat_stream_providers.js @@ -0,0 +1,61 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PassThrough } from 'stream'; + +/** + * Write the data and errors from a list of stream providers + * to a single stream in order. Stream providers are only + * called right before they will be consumed, and only one + * provider will be active at a time. + * + * @param {Array<() => ReadableStream>} sourceProviders + * @param {PassThroughOptions} options options passed to the PassThrough constructor + * @return {WritableStream} combined stream + */ +export function concatStreamProviders(sourceProviders, options = {}) { + const destination = new PassThrough(options); + const queue = sourceProviders.slice(); + + (function pipeNext() { + const provider = queue.shift(); + + if (!provider) { + return; + } + + const source = provider(); + const isLast = !queue.length; + + // if there are more sources to pipe, hook + // into the source completion + if (!isLast) { + source.once('end', pipeNext); + } + + source + // proxy errors from the source to the destination + .once('error', (error) => destination.emit('error', error)) + // pipe the source to the destination but only proxy the + // end event if this is the last source + .pipe(destination, { end: isLast }); + }()); + + return destination; +} diff --git a/src/utils/streams/index.js b/src/utils/streams/index.js index a9d8d5b7e4957b..e39bd8a4dd3428 100644 --- a/src/utils/streams/index.js +++ b/src/utils/streams/index.js @@ -1,3 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { concatStreamProviders } from './concat_stream_providers'; export { createIntersperseStream } from './intersperse_stream'; export { createSplitStream } from './split_stream'; export { createListStream } from './list_stream'; diff --git a/src/utils/streams/intersperse_stream.js b/src/utils/streams/intersperse_stream.js index 7b8d84ec0408fd..f1c352761186e7 100644 --- a/src/utils/streams/intersperse_stream.js +++ b/src/utils/streams/intersperse_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Transform } from 'stream'; /** diff --git a/src/utils/streams/json_streams.js b/src/utils/streams/json_streams.js index ab1035f79d4a81..8b58c8763d1153 100644 --- a/src/utils/streams/json_streams.js +++ b/src/utils/streams/json_streams.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Transform } from 'stream'; /** @@ -16,11 +35,16 @@ export function createJsonParseStream() { writableObjectMode: true, readableObjectMode: true, transform(json, enc, callback) { + let parsed; + let error; + try { - callback(null, JSON.parse(json)); - } catch (err) { - callback(err); + parsed = JSON.parse(json); + } catch (_error) { + error = _error; } + + callback(error, parsed); } }); } diff --git a/src/utils/streams/list_stream.js b/src/utils/streams/list_stream.js index 0f0d7f295f1cea..66b5b3ac84872f 100644 --- a/src/utils/streams/list_stream.js +++ b/src/utils/streams/list_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Readable } from 'stream'; /** diff --git a/src/utils/streams/map_stream.js b/src/utils/streams/map_stream.js index 7c10db8ea07a06..337f69261e1067 100644 --- a/src/utils/streams/map_stream.js +++ b/src/utils/streams/map_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Transform } from 'stream'; export function createMapStream(fn) { diff --git a/src/utils/streams/promise_from_streams.js b/src/utils/streams/promise_from_streams.js index 3dcbcf21171b03..1815575d1cfb62 100644 --- a/src/utils/streams/promise_from_streams.js +++ b/src/utils/streams/promise_from_streams.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Take an array of streams, pipe the output * from each one into the next, listening for diff --git a/src/utils/streams/reduce_stream.js b/src/utils/streams/reduce_stream.js index 230ee8aaa87d0e..8b8cd6ab2dbdad 100644 --- a/src/utils/streams/reduce_stream.js +++ b/src/utils/streams/reduce_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Transform } from 'stream'; /** diff --git a/src/utils/streams/replace_stream.js b/src/utils/streams/replace_stream.js index 6358dcbba5ad35..270fa9f61e2ac5 100644 --- a/src/utils/streams/replace_stream.js +++ b/src/utils/streams/replace_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Transform } from 'stream'; export function createReplaceStream(toReplace, replacement) { diff --git a/src/utils/streams/split_stream.js b/src/utils/streams/split_stream.js index 6b9cccb0813313..3bef54a288daec 100644 --- a/src/utils/streams/split_stream.js +++ b/src/utils/streams/split_stream.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { Transform } from 'stream'; /** diff --git a/src/utils/strings/__tests__/comma_separated_list.js b/src/utils/strings/__tests__/comma_separated_list.js index 1dc861d56c23e6..56820abf122536 100644 --- a/src/utils/strings/__tests__/comma_separated_list.js +++ b/src/utils/strings/__tests__/comma_separated_list.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { parseCommaSeparatedList } from '../comma_separated_list'; diff --git a/src/utils/strings/__tests__/prose.js b/src/utils/strings/__tests__/prose.js index 25db3e24d0d442..3655a828766f0c 100644 --- a/src/utils/strings/__tests__/prose.js +++ b/src/utils/strings/__tests__/prose.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { formatListAsProse } from '../prose'; diff --git a/src/utils/strings/comma_separated_list.js b/src/utils/strings/comma_separated_list.js index ab9020ba00184d..9290b999a56e11 100644 --- a/src/utils/strings/comma_separated_list.js +++ b/src/utils/strings/comma_separated_list.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function parseCommaSeparatedList(input) { if (Array.isArray(input)) { return input; diff --git a/src/utils/strings/index.js b/src/utils/strings/index.js index 94e9fcb25c72ac..430454bd572194 100644 --- a/src/utils/strings/index.js +++ b/src/utils/strings/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { parseCommaSeparatedList } from './comma_separated_list'; export { formatListAsProse } from './prose'; diff --git a/src/utils/strings/prose.js b/src/utils/strings/prose.js index 068cdcd3454982..abe001cd7493dc 100644 --- a/src/utils/strings/prose.js +++ b/src/utils/strings/prose.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /** * Converts an array of items into a sentence-ready string. * diff --git a/src/utils/unset.js b/src/utils/unset.js index 11d2f428517b2b..8b4cc0a7be1cd6 100644 --- a/src/utils/unset.js +++ b/src/utils/unset.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import toPath from 'lodash/internal/toPath'; diff --git a/src/utils/version.js b/src/utils/version.js index b2afa572f87987..173b904c1d6130 100644 --- a/src/utils/version.js +++ b/src/utils/version.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function versionSatisfies(cleanActual, cleanExpected) { try { return (cleanActual === cleanExpected); diff --git a/src/utils/watch_stdio_for_line.js b/src/utils/watch_stdio_for_line.js new file mode 100644 index 00000000000000..ed077f34035f33 --- /dev/null +++ b/src/utils/watch_stdio_for_line.js @@ -0,0 +1,79 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Transform } from 'stream'; + +import { + createPromiseFromStreams, + createSplitStream, + createMapStream, +} from './streams'; + +// creates a stream that skips empty lines unless they are followed by +// another line, preventing the empty lines produced by splitStream +function skipLastEmptyLineStream() { + let skippedEmptyLine = false; + return new Transform({ + objectMode: true, + transform(line, enc, cb) { + if (skippedEmptyLine) { + this.push(''); + skippedEmptyLine = false; + } + + if (line === '') { + skippedEmptyLine = true; + return cb(); + } else { + return cb(null, line); + } + } + }); +} + +export async function watchStdioForLine(proc, logFn, exitAfter) { + function onLogLine(line) { + logFn(line); + + if (exitAfter && exitAfter.test(line)) { + proc.kill('SIGINT'); + } + } + + await Promise.all([ + proc.catch(error => { + // ignore the error thrown by execa if it's because we killed with SIGINT + if (error.signal !== 'SIGINT') { + throw error; + } + }), + createPromiseFromStreams([ + proc.stdout, + createSplitStream('\n'), + skipLastEmptyLineStream(), + createMapStream(onLogLine), + ]), + createPromiseFromStreams([ + proc.stderr, + createSplitStream('\n'), + skipLastEmptyLineStream(), + createMapStream(onLogLine), + ]), + ]); +} diff --git a/tasks/check_plugins.js b/tasks/check_plugins.js index b1960eab86f4b5..5d6121915f740f 100644 --- a/tasks/check_plugins.js +++ b/tasks/check_plugins.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import fs from 'fs'; import path from 'path'; diff --git a/tasks/config/functional_test_runner.js b/tasks/config/functional_test_runner.js index d1f353a043fbdc..e57d823f1d4d5a 100644 --- a/tasks/config/functional_test_runner.js +++ b/tasks/config/functional_test_runner.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export const functional = { options: { logLevel: 'debug', diff --git a/tasks/config/karma.js b/tasks/config/karma.js index def1a8f298579d..d7d3057aa014e3 100644 --- a/tasks/config/karma.js +++ b/tasks/config/karma.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve, dirname } from 'path'; import { platform as getOsPlatform } from 'os'; import { times } from 'lodash'; diff --git a/tasks/config/peg.js b/tasks/config/peg.js index 1e570bb1f32194..5f5c87d266dc3c 100644 --- a/tasks/config/peg.js +++ b/tasks/config/peg.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = { legacyKuery: { src: 'src/ui/public/kuery/ast/legacy_kuery.peg', diff --git a/tasks/config/run.js b/tasks/config/run.js index 7c2cfa091db83d..69bf726f6fb3de 100644 --- a/tasks/config/run.js +++ b/tasks/config/run.js @@ -1,5 +1,23 @@ -import { esTestConfig } from '../../src/test_utils/es'; -import { kibanaTestServerUrlParts } from '../../test/kibana_test_server_url_parts'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { esTestConfig, kbnTestConfig } from '@kbn/test'; import { resolve } from 'path'; const SECOND = 1000; @@ -44,14 +62,14 @@ module.exports = function (grunt) { '--optimize.enabled=false', '--elasticsearch.url=' + esTestConfig.getUrl(), '--elasticsearch.healthCheck.delay=' + HOUR, - '--server.port=' + kibanaTestServerUrlParts.port, + '--server.port=' + kbnTestConfig.getPort(), '--server.xsrf.disableProtection=true', ]; const funcTestServerFlags = [ '--server.maxPayloadBytes=1648576', //default is 1048576 '--elasticsearch.url=' + esTestConfig.getUrl(), - '--server.port=' + kibanaTestServerUrlParts.port, + '--server.port=' + kbnTestConfig.getPort(), ]; const browserTestServerFlags = [ @@ -71,6 +89,34 @@ module.exports = function (grunt) { ] }, + // used by the test tasks + // runs the check_file_casing script to ensure filenames use correct casing + checkFileCasing: { + cmd: process.execPath, + args: [ + require.resolve('../../scripts/check_file_casing'), + '--quiet' // only log errors, not warnings + ] + }, + + // used by the test and jenkins:unit tasks + // runs the tslint script to check for Typescript linting errors + tslint: { + cmd: process.execPath, + args: [ + require.resolve('../../scripts/tslint') + ] + }, + + // used by the test:server task + // runs all node.js/server mocha tests + mocha: { + cmd: process.execPath, + args: [ + require.resolve('../../scripts/mocha') + ] + }, + // used by the test:api task // runs the kibana server prepared for the api_integration tests apiTestServer: createKbnServerTask({ diff --git a/tasks/config/simplemocha.js b/tasks/config/simplemocha.js deleted file mode 100644 index ab3b78c36ee51e..00000000000000 --- a/tasks/config/simplemocha.js +++ /dev/null @@ -1,27 +0,0 @@ -import { createAutoJunitReporter } from '../../src/dev'; - -export default { - options: { - timeout: 10000, - slow: 5000, - ignoreLeaks: false, - reporter: createAutoJunitReporter({ - reportName: 'Server Mocha Tests', - }), - globals: ['nil'], - }, - all: { - src: [ - 'test/**/__tests__/**/*.js', - 'src/**/__tests__/**/*.js', - 'packages/kbn-pm/**/__tests__/**/*.js', - 'packages/kbn-datemath/test/**/*.js', - 'packages/kbn-dev-utils/**/__tests__/**/*.js', - 'tasks/**/__tests__/**/*.js', - 'test/fixtures/__tests__/*.js', - '!**/__tests__/fixtures/**/*', - '!src/**/public/**', - '!**/_*.js', - ], - }, -}; diff --git a/tasks/config/watch.js b/tasks/config/watch.js index d47da445687d27..e4ae817d6b2d9f 100644 --- a/tasks/config/watch.js +++ b/tasks/config/watch.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = { peg: { files: ['src/ui/public/kuery/ast/*.peg'], diff --git a/tasks/docker_docs.js b/tasks/docker_docs.js index e609f7310d385d..1c35f44eb65385 100644 --- a/tasks/docker_docs.js +++ b/tasks/docker_docs.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import rimraf from 'rimraf'; import { join } from 'path'; import { execFileSync as exec } from 'child_process'; diff --git a/tasks/functional_test_runner.js b/tasks/functional_test_runner.js index 36fd928e8a596b..1c72b50d849f87 100644 --- a/tasks/functional_test_runner.js +++ b/tasks/functional_test_runner.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { createFunctionalTestRunner } from '../src/functional_test_runner'; import { createToolingLog } from '@kbn/dev-utils'; diff --git a/tasks/jenkins.js b/tasks/jenkins.js index 0b6844775075d0..daece61ea4c789 100644 --- a/tasks/jenkins.js +++ b/tasks/jenkins.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = function (grunt) { grunt.registerTask('jenkins:docs', [ 'docker:docs' @@ -5,7 +24,10 @@ module.exports = function (grunt) { grunt.registerTask('jenkins:unit', [ 'run:eslint', + 'run:tslint', + 'run:checkFileCasing', 'licenses', + 'verifyDependencyVersions', 'run:verifyNotice', 'test:server', 'test:jest', diff --git a/tasks/licenses.js b/tasks/licenses.js index 431692d713e2bf..30baf9a808e5df 100644 --- a/tasks/licenses.js +++ b/tasks/licenses.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { getInstalledPackages } from '../src/dev/npm'; import { assertLicensesValid, diff --git a/tasks/licenses_csv_report.js b/tasks/licenses_csv_report.js index c3520148c69a1c..a24e15aaf28eb5 100644 --- a/tasks/licenses_csv_report.js +++ b/tasks/licenses_csv_report.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { writeFileSync } from 'fs'; import { resolve } from 'path'; import { getInstalledPackages } from '../src/dev/npm'; diff --git a/tasks/sterilize.js b/tasks/sterilize.js index 9ea2b3d5b92fe3..d0b4fb15c5c6eb 100644 --- a/tasks/sterilize.js +++ b/tasks/sterilize.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { bgRed, white } from 'chalk'; import { execSync } from 'child_process'; import { createInterface } from 'readline'; diff --git a/tasks/test.js b/tasks/test.js index 5e92c2d86e90c3..af6ac2e7779e8e 100644 --- a/tasks/test.js +++ b/tasks/test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _, { keys } from 'lodash'; import { run } from '../utilities/visual_regression'; @@ -14,7 +33,7 @@ module.exports = function (grunt) { grunt.registerTask('test:server', [ 'checkPlugins', - 'simplemocha:all', + 'run:mocha', ]); grunt.registerTask('test:browser', [ @@ -100,6 +119,8 @@ module.exports = function (grunt) { grunt.task.run(_.compact([ !grunt.option('quick') && 'run:eslint', + !grunt.option('quick') && 'run:tslint', + 'run:checkFileCasing', 'licenses', 'test:quick', 'verifyTranslations', diff --git a/tasks/test_jest.js b/tasks/test_jest.js index 8f9340d9d75025..b19220fef70a4c 100644 --- a/tasks/test_jest.js +++ b/tasks/test_jest.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + const { resolve } = require('path'); module.exports = function (grunt) { diff --git a/tasks/utils/i18n_verify_keys.js b/tasks/utils/i18n_verify_keys.js index f45c6c7b00f7e2..6dba675e844706 100644 --- a/tasks/utils/i18n_verify_keys.js +++ b/tasks/utils/i18n_verify_keys.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import fs from 'fs'; import glob from 'glob'; import path from 'path'; diff --git a/tasks/verify_dependency_versions.js b/tasks/verify_dependency_versions.js new file mode 100644 index 00000000000000..74c926f27f492b --- /dev/null +++ b/tasks/verify_dependency_versions.js @@ -0,0 +1,62 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { size } from 'lodash'; +import kibana from '../package.json'; +import xpack from '../x-pack/package.json'; + +function getMismatches(depType) { + return Object.keys(kibana[depType]) + .map(key => { + const xpackValue = xpack[depType][key]; + const kibanaValue = kibana[depType][key]; + if ( + xpackValue && + kibanaValue && + xpackValue !== kibanaValue && + !key.includes('@kbn/') + ) { + return { + key, + xpack: xpackValue, + kibana: kibanaValue, + }; + } + }) + .filter(key => !!key); +} + +export default function verifyDependencyVersions(grunt) { + grunt.registerTask( + 'verifyDependencyVersions', + 'Checks dependency versions', + () => { + const devDependenciesMismatches = getMismatches('devDependencies'); + if (size(devDependenciesMismatches) > 0) { + grunt.log.error( + 'The following devDependencies do not match:', + JSON.stringify(devDependenciesMismatches, null, 4) + ); + return false; + } else { + grunt.log.writeln('devDependencies match!'); + } + } + ); +} diff --git a/tasks/verify_translations.js b/tasks/verify_translations.js index f9018264714611..045753fa8ade02 100644 --- a/tasks/verify_translations.js +++ b/tasks/verify_translations.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fromRoot, formatListAsProse } from '../src/utils'; import { findPluginSpecs } from '../src/plugin_discovery'; import { collectUiExports } from '../src/ui'; diff --git a/test/api_integration/apis/elasticsearch/index.js b/test/api_integration/apis/elasticsearch/index.js index 5caede5b5e732a..8cfbee4053d7c8 100644 --- a/test/api_integration/apis/elasticsearch/index.js +++ b/test/api_integration/apis/elasticsearch/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); diff --git a/test/api_integration/apis/general/cookies.js b/test/api_integration/apis/general/cookies.js index 5b5709a2772800..d377ca1eac6ba2 100644 --- a/test/api_integration/apis/general/cookies.js +++ b/test/api_integration/apis/general/cookies.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/general/index.js b/test/api_integration/apis/general/index.js index 1cf51d0b3c4598..ed8aefdcdc7489 100644 --- a/test/api_integration/apis/general/index.js +++ b/test/api_integration/apis/general/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('general', () => { loadTestFile(require.resolve('./cookies')); diff --git a/test/api_integration/apis/index.js b/test/api_integration/apis/index.js index 1810947efc9857..62cc316cac2b8a 100644 --- a/test/api_integration/apis/index.js +++ b/test/api_integration/apis/index.js @@ -1,13 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('apis', () => { loadTestFile(require.resolve('./elasticsearch')); loadTestFile(require.resolve('./general')); loadTestFile(require.resolve('./index_patterns')); + loadTestFile(require.resolve('./management')); loadTestFile(require.resolve('./saved_objects')); loadTestFile(require.resolve('./scripts')); loadTestFile(require.resolve('./search')); loadTestFile(require.resolve('./shorten')); loadTestFile(require.resolve('./suggestions')); loadTestFile(require.resolve('./status')); + loadTestFile(require.resolve('./stats')); }); } diff --git a/test/api_integration/apis/index_patterns/es_errors/errors.js b/test/api_integration/apis/index_patterns/es_errors/errors.js index 46b7ab75d41fca..9a0871576e2677 100644 --- a/test/api_integration/apis/index_patterns/es_errors/errors.js +++ b/test/api_integration/apis/index_patterns/es_errors/errors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { errors as esErrors } from 'elasticsearch'; import Boom from 'boom'; diff --git a/test/api_integration/apis/index_patterns/es_errors/index.js b/test/api_integration/apis/index_patterns/es_errors/index.js index d32a52835a45ef..38c67dbfc389fb 100644 --- a/test/api_integration/apis/index_patterns/es_errors/index.js +++ b/test/api_integration/apis/index_patterns/es_errors/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('index_patterns/service/lib', () => { loadTestFile(require.resolve('./errors')); diff --git a/test/api_integration/apis/index_patterns/es_errors/lib/get_es_errors.js b/test/api_integration/apis/index_patterns/es_errors/lib/get_es_errors.js index 40e914339ee1df..da375e76d54b78 100644 --- a/test/api_integration/apis/index_patterns/es_errors/lib/get_es_errors.js +++ b/test/api_integration/apis/index_patterns/es_errors/lib/get_es_errors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export async function getIndexNotFoundError(es) { diff --git a/test/api_integration/apis/index_patterns/es_errors/lib/index.js b/test/api_integration/apis/index_patterns/es_errors/lib/index.js index 7f5916190c0451..c65a30ef72644c 100644 --- a/test/api_integration/apis/index_patterns/es_errors/lib/index.js +++ b/test/api_integration/apis/index_patterns/es_errors/lib/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { getIndexNotFoundError, getDocNotFoundError, diff --git a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/errors.js b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/errors.js index 50b779f49459a3..0e8423ba5725f9 100644 --- a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/errors.js +++ b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/errors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService }) { const supertest = getService('supertest'); diff --git a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/index.js b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/index.js index bab744620c25ae..58d8ac6ebca2ff 100644 --- a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/index.js +++ b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('index_patterns/_fields_for_time_pattern', () => { loadTestFile(require.resolve('./errors')); diff --git a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/pattern.js b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/pattern.js index d10999db1d4e26..58f5407f81de3f 100644 --- a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/pattern.js +++ b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/pattern.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js index a4d4e5535b857d..c8030fd3e4e89f 100644 --- a/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js +++ b/test/api_integration/apis/index_patterns/fields_for_time_pattern_route/query_params.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js index 0c2aab44d09882..f0f9d73dc6ec1a 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/conflicts.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/index.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/index.js index 6f4ce4169afcfd..4dc33c7ef5e0cf 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/index.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('index_patterns/_fields_for_wildcard route', () => { loadTestFile(require.resolve('./params')); diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js index 94f668dbd9fbcd..21d254c739b29e 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/params.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService }) { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); diff --git a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js index 4458ed3c813ef3..26497d317f2720 100644 --- a/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js +++ b/test/api_integration/apis/index_patterns/fields_for_wildcard_route/response.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { sortBy } from 'lodash'; diff --git a/test/api_integration/apis/index_patterns/index.js b/test/api_integration/apis/index_patterns/index.js index fd6320b974f891..42f907ff8aec15 100644 --- a/test/api_integration/apis/index_patterns/index.js +++ b/test/api_integration/apis/index_patterns/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('index_patterns', () => { loadTestFile(require.resolve('./es_errors')); diff --git a/test/api_integration/apis/management/index.js b/test/api_integration/apis/management/index.js new file mode 100644 index 00000000000000..79c2f7e7f8c75d --- /dev/null +++ b/test/api_integration/apis/management/index.js @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export default function ({ loadTestFile }) { + describe('management apis', () => { + loadTestFile(require.resolve('./saved_objects')); + }); +} diff --git a/test/api_integration/apis/management/saved_objects/index.js b/test/api_integration/apis/management/saved_objects/index.js new file mode 100644 index 00000000000000..6f753b9bda688e --- /dev/null +++ b/test/api_integration/apis/management/saved_objects/index.js @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export default function ({ loadTestFile }) { + describe('saved_objects', () => { + loadTestFile(require.resolve('./relationships')); + }); +} diff --git a/test/api_integration/apis/management/saved_objects/relationships.js b/test/api_integration/apis/management/saved_objects/relationships.js new file mode 100644 index 00000000000000..9f11dbb8f132ec --- /dev/null +++ b/test/api_integration/apis/management/saved_objects/relationships.js @@ -0,0 +1,118 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +export default function ({ getService }) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('relationships', () => { + before(() => esArchiver.load('management/saved_objects')); + after(() => esArchiver.unload('management/saved_objects')); + + it('should work for searches', async () => { + await supertest + .get( + `/api/kibana/management/saved_objects/relationships/search/960372e0-3224-11e8-a572-ffca06da1357` + ) + .expect(200) + .then(resp => { + expect(resp.body).to.eql({ + visualizations: [ + { + id: 'a42c0580-3224-11e8-a572-ffca06da1357', + title: 'VisualizationFromSavedSearch', + }, + ], + indexPatterns: [ + { + id: '8963ca30-3224-11e8-a572-ffca06da1357', + title: 'saved_objects*', + }, + ], + }); + }); + }); + + it('should work for dashboards', async () => { + await supertest + .get( + `/api/kibana/management/saved_objects/relationships/dashboard/b70c7ae0-3224-11e8-a572-ffca06da1357` + ) + .expect(200) + .then(resp => { + expect(resp.body).to.eql({ + visualizations: [ + { + id: 'add810b0-3224-11e8-a572-ffca06da1357', + title: 'Visualization', + }, + { + id: 'a42c0580-3224-11e8-a572-ffca06da1357', + title: 'VisualizationFromSavedSearch', + }, + ], + }); + }); + }); + + it('should work for visualizations', async () => { + await supertest + .get( + `/api/kibana/management/saved_objects/relationships/visualization/a42c0580-3224-11e8-a572-ffca06da1357` + ) + .expect(200) + .then(resp => { + expect(resp.body).to.eql({ + dashboards: [ + { + id: 'b70c7ae0-3224-11e8-a572-ffca06da1357', + title: 'Dashboard', + }, + ], + }); + }); + }); + + it('should work for index patterns', async () => { + await supertest + .get( + `/api/kibana/management/saved_objects/relationships/index-pattern/8963ca30-3224-11e8-a572-ffca06da1357` + ) + .expect(200) + .then(resp => { + expect(resp.body).to.eql({ + searches: [ + { + id: '960372e0-3224-11e8-a572-ffca06da1357', + title: 'OneRecord', + }, + ], + visualizations: [ + { + id: 'add810b0-3224-11e8-a572-ffca06da1357', + title: 'Visualization', + }, + ], + }); + }); + }); + }); +} diff --git a/test/api_integration/apis/saved_objects/bulk_get.js b/test/api_integration/apis/saved_objects/bulk_get.js index 63aed397a363ce..e8d2bb77973e8a 100644 --- a/test/api_integration/apis/saved_objects/bulk_get.js +++ b/test/api_integration/apis/saved_objects/bulk_get.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/saved_objects/create.js b/test/api_integration/apis/saved_objects/create.js index 37f6ef7893a468..516ca618da2ddb 100644 --- a/test/api_integration/apis/saved_objects/create.js +++ b/test/api_integration/apis/saved_objects/create.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/saved_objects/delete.js b/test/api_integration/apis/saved_objects/delete.js index 39e239936e9d05..d2610e00e25295 100644 --- a/test/api_integration/apis/saved_objects/delete.js +++ b/test/api_integration/apis/saved_objects/delete.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/saved_objects/find.js b/test/api_integration/apis/saved_objects/find.js index 5822923363d146..1b8096ae048c97 100644 --- a/test/api_integration/apis/saved_objects/find.js +++ b/test/api_integration/apis/saved_objects/find.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/saved_objects/get.js b/test/api_integration/apis/saved_objects/get.js index d44e76be86d23a..e2f8cf5071c606 100644 --- a/test/api_integration/apis/saved_objects/get.js +++ b/test/api_integration/apis/saved_objects/get.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/saved_objects/index.js b/test/api_integration/apis/saved_objects/index.js index 62c9802da29ea5..c7694557c836c9 100644 --- a/test/api_integration/apis/saved_objects/index.js +++ b/test/api_integration/apis/saved_objects/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('saved_objects', () => { loadTestFile(require.resolve('./bulk_get')); diff --git a/test/api_integration/apis/saved_objects/update.js b/test/api_integration/apis/saved_objects/update.js index e1afc1bb691449..00a0fa04908e17 100644 --- a/test/api_integration/apis/saved_objects/update.js +++ b/test/api_integration/apis/saved_objects/update.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/scripts/index.js b/test/api_integration/apis/scripts/index.js index 2884b3bf4c0e5b..6f27dee3e045ee 100644 --- a/test/api_integration/apis/scripts/index.js +++ b/test/api_integration/apis/scripts/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('scripts', () => { loadTestFile(require.resolve('./languages')); diff --git a/test/api_integration/apis/scripts/languages.js b/test/api_integration/apis/scripts/languages.js index ae2707df2fc63a..b8145f0344682f 100644 --- a/test/api_integration/apis/scripts/languages.js +++ b/test/api_integration/apis/scripts/languages.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/search/count.js b/test/api_integration/apis/search/count.js index e843b09ae17ff5..1fc4cbf9b6ad1c 100644 --- a/test/api_integration/apis/search/count.js +++ b/test/api_integration/apis/search/count.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/search/index.js b/test/api_integration/apis/search/index.js index 99f3555d54eec2..37f34cf2bbd142 100644 --- a/test/api_integration/apis/search/index.js +++ b/test/api_integration/apis/search/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('search', () => { loadTestFile(require.resolve('./count')); diff --git a/test/api_integration/apis/shorten/index.js b/test/api_integration/apis/shorten/index.js index 80703b41d80990..172f6dc3be4366 100644 --- a/test/api_integration/apis/shorten/index.js +++ b/test/api_integration/apis/shorten/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { diff --git a/test/api_integration/apis/stats/index.js b/test/api_integration/apis/stats/index.js new file mode 100644 index 00000000000000..902a36558afc31 --- /dev/null +++ b/test/api_integration/apis/stats/index.js @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export default function ({ loadTestFile }) { + describe('stats', () => { + loadTestFile(require.resolve('./stats')); + }); +} + diff --git a/test/api_integration/apis/stats/stats.js b/test/api_integration/apis/stats/stats.js new file mode 100644 index 00000000000000..6e9bbb801482f4 --- /dev/null +++ b/test/api_integration/apis/stats/stats.js @@ -0,0 +1,105 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +const assertStatsAndMetrics = body => { + expect(body.status.overall.state).to.be('green'); + expect(body.status.statuses).to.be.an('array'); + const kibanaPlugin = body.status.statuses.find(s => { + return s.id.indexOf('plugin:kibana') === 0; + }); + expect(kibanaPlugin.state).to.be('green'); + + expect(body.name).to.be.a('string'); + expect(body.uuid).to.be.a('string'); + + expect(body.version.number).to.be.a('string'); + + expect(body.process.mem.external_in_bytes).to.be.an('number'); + expect(body.process.mem.heap_max_in_bytes).to.be.an('number'); + expect(body.process.mem.heap_used_in_bytes).to.be.an('number'); + expect(body.process.mem.resident_set_size_in_bytes).to.be.an('number'); + expect(body.process.pid).to.be.an('number'); + expect(body.process.uptime_ms).to.be.an('number'); + + expect(body.os.cpu.load_average['1m']).to.be.a('number'); + + expect(body.response_times.avg_in_millis).not.to.be(null); // ok if is undefined + expect(body.response_times.max_in_millis).not.to.be(null); // ok if is undefined + + expect(body.requests.status_codes).to.be.an('object'); + + expect(body.sockets.http).to.be.an('object'); + expect(body.sockets.https).to.be.an('object'); + + expect(body.concurrent_connections).to.be.a('number'); + + expect(body.event_loop_delay).to.be.an('number'); +}; + +export default function ({ getService }) { + const supertest = getService('supertest'); + + describe('kibana stats api', () => { + it('should return the stats and metric fields without cluster_uuid when extended param is not present', () => { + return supertest + .get('/api/stats') + .expect('Content-Type', /json/) + .expect(200) + .then(({ body }) => { + expect(body.cluster_uuid).to.be(undefined); + assertStatsAndMetrics(body); + }); + }); + it('should return the stats and metric fields without cluster_uuid when extended param is given as false', () => { + return supertest + .get('/api/stats?extended=false') + .expect('Content-Type', /json/) + .expect(200) + .then(({ body }) => { + expect(body.cluster_uuid).to.be(undefined); + assertStatsAndMetrics(body); + }); + }); + + it('should return the stats and metric fields with cluster_uuid when extended param is present', () => { + return supertest + .get('/api/stats?extended') + .expect('Content-Type', /json/) + .expect(200) + .then(({ body }) => { + expect(body.cluster_uuid).to.be.a('string'); + assertStatsAndMetrics(body); + }); + }); + + it('should return the stats and metric fields with cluster_uuid when extended param is given as true', () => { + return supertest + .get('/api/stats?extended=true') + .expect('Content-Type', /json/) + .expect(200) + .then(({ body }) => { + expect(body.cluster_uuid).to.be.a('string'); + assertStatsAndMetrics(body); + }); + }); + }); +} + diff --git a/test/api_integration/apis/status/index.js b/test/api_integration/apis/status/index.js index 78bd2b6f695a57..21e526adfa2932 100644 --- a/test/api_integration/apis/status/index.js +++ b/test/api_integration/apis/status/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('status', () => { loadTestFile(require.resolve('./status')); diff --git a/test/api_integration/apis/status/status.js b/test/api_integration/apis/status/status.js index 8d1a783e5977f5..a64bdc8ebf8622 100644 --- a/test/api_integration/apis/status/status.js +++ b/test/api_integration/apis/status/status.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService }) { @@ -34,9 +53,8 @@ export default function ({ getService }) { expect(body.metrics.os.cpu.load_average['5m']).to.be.a('number'); expect(body.metrics.os.cpu.load_average['15m']).to.be.a('number'); - // TODO: fix this in the status/metrics class so this is always defined - // expect(body.metrics.response_times.avg_in_millis).not.to.be(undefined); // a number, but is null if no measurements have yet been collected for averaging - expect(body.metrics.response_times.max_in_millis).to.be.a('number'); + expect(body.metrics.response_times.avg_in_millis).not.to.be(null); // ok if undefined + expect(body.metrics.response_times.max_in_millis).not.to.be(null); // ok if undefined expect(body.metrics.requests.total).to.be.a('number'); expect(body.metrics.requests.disconnects).to.be.a('number'); diff --git a/test/api_integration/apis/suggestions/index.js b/test/api_integration/apis/suggestions/index.js index 961a54cd7a2758..20bc1dea2c3c6b 100644 --- a/test/api_integration/apis/suggestions/index.js +++ b/test/api_integration/apis/suggestions/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ loadTestFile }) { describe('suggestions', () => { loadTestFile(require.resolve('./suggestions')); diff --git a/test/api_integration/apis/suggestions/suggestions.js b/test/api_integration/apis/suggestions/suggestions.js index 9143f208bdc5bf..80b6febb81d7b6 100644 --- a/test/api_integration/apis/suggestions/suggestions.js +++ b/test/api_integration/apis/suggestions/suggestions.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService }) { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); diff --git a/test/api_integration/config.js b/test/api_integration/config.js index a9518b4f831804..dbc69eee91a95b 100644 --- a/test/api_integration/config.js +++ b/test/api_integration/config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { KibanaSupertestProvider, ElasticsearchSupertestProvider, @@ -6,6 +25,7 @@ import { export default async function ({ readConfigFile }) { const commonConfig = await readConfigFile(require.resolve('../common/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config')); return { testFiles: [ @@ -22,6 +42,17 @@ export default async function ({ readConfigFile }) { servers: commonConfig.get('servers'), junit: { reportName: 'API Integration Tests' - } + }, + env: commonConfig.get('env'), + esTestCluster: commonConfig.get('esTestCluster'), + kbnTestServer: { + ...functionalConfig.get('kbnTestServer'), + serverArgs: [ + ...functionalConfig.get('kbnTestServer.serverArgs'), + '--optimize.enabled=false', + '--elasticsearch.healthCheck.delay=3600000', + '--server.xsrf.disableProtection=true', + ], + }, }; } diff --git a/test/api_integration/fixtures/es_archiver/management/saved_objects/data.json.gz b/test/api_integration/fixtures/es_archiver/management/saved_objects/data.json.gz new file mode 100644 index 00000000000000..3835470826ab65 Binary files /dev/null and b/test/api_integration/fixtures/es_archiver/management/saved_objects/data.json.gz differ diff --git a/x-pack/test/functional/es_archives/reporting/6_2/mappings.json b/test/api_integration/fixtures/es_archiver/management/saved_objects/mappings.json similarity index 80% rename from x-pack/test/functional/es_archives/reporting/6_2/mappings.json rename to test/api_integration/fixtures/es_archiver/management/saved_objects/mappings.json index 48cd01eb935c96..582e976c3cca03 100644 --- a/x-pack/test/functional/es_archives/reporting/6_2/mappings.json +++ b/test/api_integration/fixtures/es_archiver/management/saved_objects/mappings.json @@ -5,11 +5,13 @@ "settings": { "index": { "number_of_shards": "1", - "number_of_replicas": "1" + "auto_expand_replicas": "0-1", + "number_of_replicas": "0" } }, "mappings": { "doc": { + "dynamic": "strict", "properties": { "config": { "dynamic": "true", @@ -26,13 +28,12 @@ } } }, - "xPackMonitoring:showBanner": { + "telemetry:optIn": { "type": "boolean" } } }, "dashboard": { - "dynamic": "strict", "properties": { "description": { "type": "text" @@ -90,7 +91,6 @@ } }, "graph-workspace": { - "dynamic": "strict", "properties": { "description": { "type": "text" @@ -120,7 +120,6 @@ } }, "index-pattern": { - "dynamic": "strict", "properties": { "fieldFormatMap": { "type": "text" @@ -146,7 +145,6 @@ } }, "search": { - "dynamic": "strict", "properties": { "columns": { "type": "keyword" @@ -176,7 +174,6 @@ } }, "server": { - "dynamic": "strict", "properties": { "uuid": { "type": "keyword" @@ -184,7 +181,6 @@ } }, "timelion-sheet": { - "dynamic": "strict", "properties": { "description": { "type": "text" @@ -232,7 +228,6 @@ "type": "date" }, "url": { - "dynamic": "strict", "properties": { "accessCount": { "type": "long" @@ -255,7 +250,6 @@ } }, "visualization": { - "dynamic": "strict", "properties": { "description": { "type": "text" @@ -288,75 +282,4 @@ } } } -} - -{ - "type": "index", - "value": { - "index": ".reporting-2018.03.11", - "settings": { - "index": { - "number_of_shards": "1", - "auto_expand_replicas": "0-1", - "number_of_replicas": "0" - } - }, - "mappings": { - "esqueue": { - "properties": { - "attempts": { - "type": "short" - }, - "completed_at": { - "type": "date" - }, - "created_at": { - "type": "date" - }, - "created_by": { - "type": "keyword" - }, - "jobtype": { - "type": "keyword" - }, - "max_attempts": { - "type": "short" - }, - "output": { - "properties": { - "content": { - "type": "object", - "enabled": false - }, - "content_type": { - "type": "keyword" - }, - "max_size_reached": { - "type": "boolean" - } - } - }, - "payload": { - "type": "object", - "enabled": false - }, - "priority": { - "type": "byte" - }, - "process_expiration": { - "type": "date" - }, - "started_at": { - "type": "date" - }, - "status": { - "type": "keyword" - }, - "timeout": { - "type": "long" - } - } - } - } - } } \ No newline at end of file diff --git a/test/api_integration/services/chance.js b/test/api_integration/services/chance.js index 8f16c30b83d9d8..3c5d9dc704aae0 100644 --- a/test/api_integration/services/chance.js +++ b/test/api_integration/services/chance.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Chance from 'chance'; export function ChanceProvider({ getService }) { diff --git a/test/api_integration/services/index.js b/test/api_integration/services/index.js index 157cc22ade9edb..2d363d1ac552ba 100644 --- a/test/api_integration/services/index.js +++ b/test/api_integration/services/index.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KibanaSupertestProvider, ElasticsearchSupertestProvider } from './supertest'; export { ChanceProvider } from './chance'; diff --git a/test/api_integration/services/supertest.js b/test/api_integration/services/supertest.js index c456172f233788..b53b4ae0ef32f6 100644 --- a/test/api_integration/services/supertest.js +++ b/test/api_integration/services/supertest.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { format as formatUrl } from 'url'; import supertestAsPromised from 'supertest-as-promised'; diff --git a/test/common/config.js b/test/common/config.js index 40973b7ad609eb..4c80382918f303 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -1,3 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { format as formatUrl } from 'url'; +import { OPTIMIZE_BUNDLE_DIR, esTestConfig, kbnTestConfig } from '@kbn/test'; import { KibanaServerProvider, EsProvider, @@ -5,15 +26,42 @@ import { RetryProvider, } from './services'; -import { esTestConfig } from '../../src/test_utils/es'; -import { kibanaTestServerUrlParts } from '../kibana_test_server_url_parts'; - export default function () { + const servers = { + kibana: kbnTestConfig.getUrlParts(), + elasticsearch: esTestConfig.getUrlParts(), + }; + return { - servers: { - kibana: kibanaTestServerUrlParts, - elasticsearch: esTestConfig.getUrlParts(), + servers, + + esTestCluster: { + license: 'oss', + from: 'snapshot', + serverArgs: [ + ], + }, + + kbnTestServer: { + buildArgs: [ '--optimize.useBundleCache=true' ], + sourceArgs: [ + '--no-base-path', + `--optimize.bundleDir=${OPTIMIZE_BUNDLE_DIR}`, + ], + serverArgs: [ + '--env=development', + '--logging.json=false', + `--server.port=${kbnTestConfig.getPort()}`, + `--optimize.watchPort=${kbnTestConfig.getPort()}`, + '--optimize.watchPrebuild=true', + '--status.allowAnonymous=true', + '--optimize.enabled=true', + `--elasticsearch.url=${formatUrl(servers.elasticsearch)}`, + `--elasticsearch.username=${servers.elasticsearch.username}`, + `--elasticsearch.password=${servers.elasticsearch.password}`, + ], }, + services: { kibanaServer: KibanaServerProvider, retry: RetryProvider, diff --git a/test/common/services/es.js b/test/common/services/es.js index a4c0d5b054e250..73e6ccb6a63aaa 100644 --- a/test/common/services/es.js +++ b/test/common/services/es.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { format as formatUrl } from 'url'; import elasticsearch from 'elasticsearch'; diff --git a/test/common/services/es_archiver.js b/test/common/services/es_archiver.js index 6e3e5b2aa561a0..8dd796e70bd4f4 100644 --- a/test/common/services/es_archiver.js +++ b/test/common/services/es_archiver.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { EsArchiver } from '../../../src/es_archiver'; export async function EsArchiverProvider({ getService }) { diff --git a/test/common/services/index.js b/test/common/services/index.js index 42c80c4e1ed5e8..c9a5813e1e8509 100644 --- a/test/common/services/index.js +++ b/test/common/services/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KibanaServerProvider } from './kibana_server'; export { EsProvider } from './es'; export { EsArchiverProvider } from './es_archiver'; diff --git a/test/common/services/kibana_server/index.js b/test/common/services/kibana_server/index.js index a0a934e4cac9b4..70b4e934e30dc1 100644 --- a/test/common/services/kibana_server/index.js +++ b/test/common/services/kibana_server/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { KibanaServerProvider } from './kibana_server'; diff --git a/test/common/services/kibana_server/kibana_server.js b/test/common/services/kibana_server/kibana_server.js index 770aaa759ba64b..5f413fe0b58d1c 100644 --- a/test/common/services/kibana_server/kibana_server.js +++ b/test/common/services/kibana_server/kibana_server.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { format as formatUrl } from 'url'; import { KibanaServerStatus } from './status'; diff --git a/test/common/services/kibana_server/status.js b/test/common/services/kibana_server/status.js index e6af5e5d419823..19af8c4d6f2581 100644 --- a/test/common/services/kibana_server/status.js +++ b/test/common/services/kibana_server/status.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve as resolveUrl } from 'url'; import { fromNode } from 'bluebird'; diff --git a/test/common/services/kibana_server/ui_settings.js b/test/common/services/kibana_server/ui_settings.js index 5d08b0291520d0..8971a012f64b9b 100644 --- a/test/common/services/kibana_server/ui_settings.js +++ b/test/common/services/kibana_server/ui_settings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Wreck from 'wreck'; import { get } from 'lodash'; diff --git a/test/common/services/kibana_server/version.js b/test/common/services/kibana_server/version.js index 2cf1cacadef7c9..1b13ba6c411ab2 100644 --- a/test/common/services/kibana_server/version.js +++ b/test/common/services/kibana_server/version.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export class KibanaServerVersion { constructor(kibanaStatus) { this.kibanaStatus = kibanaStatus; diff --git a/test/common/services/retry.js b/test/common/services/retry.js index a5976dd0743d5d..a6d7f3c8407d3b 100644 --- a/test/common/services/retry.js +++ b/test/common/services/retry.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import bluebird from 'bluebird'; export function RetryProvider({ getService }) { diff --git a/test/functional/apps/console/_console.js b/test/functional/apps/console/_console.js index ee46905a081992..05350097c0bdde 100644 --- a/test/functional/apps/console/_console.js +++ b/test/functional/apps/console/_console.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; const DEFAULT_REQUEST = ` diff --git a/test/functional/apps/console/index.js b/test/functional/apps/console/index.js index b92e865cc05d23..2436f5bb3884bc 100644 --- a/test/functional/apps/console/index.js +++ b/test/functional/apps/console/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, loadTestFile }) { const remote = getService('remote'); diff --git a/test/functional/apps/context/_discover_navigation.js b/test/functional/apps/context/_discover_navigation.js index 5efa4886ecaad6..6be4400add1411 100644 --- a/test/functional/apps/context/_discover_navigation.js +++ b/test/functional/apps/context/_discover_navigation.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; const TEST_DISCOVER_START_TIME = '2015-09-19 06:31:44.000'; diff --git a/test/functional/apps/context/_filters.js b/test/functional/apps/context/_filters.js index 374bad57c3f5e6..6d1bf421eea9b2 100644 --- a/test/functional/apps/context/_filters.js +++ b/test/functional/apps/context/_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; const TEST_INDEX_PATTERN = 'logstash-*'; diff --git a/test/functional/apps/context/_size.js b/test/functional/apps/context/_size.js index c37e75f93e0766..907db00fb5f861 100644 --- a/test/functional/apps/context/_size.js +++ b/test/functional/apps/context/_size.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; const TEST_INDEX_PATTERN = 'logstash-*'; diff --git a/test/functional/apps/context/index.js b/test/functional/apps/context/index.js index 62064e9a827fb2..d925269dd434b9 100644 --- a/test/functional/apps/context/index.js +++ b/test/functional/apps/context/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, getPageObjects, loadTestFile }) { const remote = getService('remote'); const esArchiver = getService('esArchiver'); diff --git a/test/functional/apps/dashboard/_bwc_shared_urls.js b/test/functional/apps/dashboard/_bwc_shared_urls.js index 19620d1774a839..581e6e7c6df12e 100644 --- a/test/functional/apps/dashboard/_bwc_shared_urls.js +++ b/test/functional/apps/dashboard/_bwc_shared_urls.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -5,6 +24,7 @@ export default function ({ getService, getPageObjects }) { const dashboardExpect = getService('dashboardExpect'); const remote = getService('remote'); const log = getService('log'); + const queryBar = getService('queryBar'); let kibanaBaseUrl; @@ -44,7 +64,7 @@ export default function ({ getService, getPageObjects }) { await remote.get(url, true); await PageObjects.header.waitUntilLoadingHasFinished(); - const query = await PageObjects.dashboard.getQuery(); + const query = await queryBar.getQueryString(); expect(query).to.equal('memory:>220000'); await dashboardExpect.pieSliceCount(5); @@ -60,7 +80,7 @@ export default function ({ getService, getPageObjects }) { await remote.get(url, true); await PageObjects.header.waitUntilLoadingHasFinished(); - const query = await PageObjects.dashboard.getQuery(); + const query = await queryBar.getQueryString(); expect(query).to.equal('memory:>220000'); await dashboardExpect.pieSliceCount(5); diff --git a/test/functional/apps/dashboard/_create_and_add_embeddables.js b/test/functional/apps/dashboard/_create_and_add_embeddables.js new file mode 100644 index 00000000000000..6a6b4a539a39c1 --- /dev/null +++ b/test/functional/apps/dashboard/_create_and_add_embeddables.js @@ -0,0 +1,101 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +import { + VisualizeConstants +} from '../../../../src/core_plugins/kibana/public/visualize/visualize_constants'; + +export default function ({ getService, getPageObjects }) { + const retry = getService('retry'); + const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'settings', 'common']); + const remote = getService('remote'); + const dashboardAddPanel = getService('dashboardAddPanel'); + + describe('create and add embeddables', async () => { + before(async () => { + await PageObjects.dashboard.loadSavedDashboard('few panels'); + }); + + describe('add new visualization link', () => { + it('adds a new visualization', async () => { + const originalPanelCount = await PageObjects.dashboard.getPanelCount(); + await PageObjects.dashboard.clickEdit(); + await dashboardAddPanel.ensureAddPanelIsShowing(); + await dashboardAddPanel.clickAddNewEmbeddableLink(); + await PageObjects.visualize.clickAreaChart(); + await PageObjects.visualize.clickNewSearch(); + await PageObjects.visualize.saveVisualization('visualization from add new link'); + + return retry.try(async () => { + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.eql(originalPanelCount + 1); + }); + }); + + it('saves the saved visualization url to the app link', async () => { + await PageObjects.header.clickVisualize(); + const currentUrl = await remote.getCurrentUrl(); + expect(currentUrl).to.contain(VisualizeConstants.EDIT_PATH); + }); + + after(async () => { + await PageObjects.header.clickDashboard(); + }); + }); + + describe('visualize:enableLabs advanced setting', () => { + const LAB_VIS_NAME = 'Rendering Test: input control'; + + it('should display lab visualizations in add panel', async () => { + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.clickNewDashboard(); + const exists = await dashboardAddPanel.panelAddLinkExists(LAB_VIS_NAME); + await dashboardAddPanel.closeAddPanel(); + expect(exists).to.be(true); + }); + + describe('is false', () => { + before(async () => { + await PageObjects.header.clickManagement(); + await PageObjects.settings.clickKibanaSettings(); + await PageObjects.settings.toggleAdvancedSettingCheckbox('visualize:enableLabs'); + }); + + it('should not display lab visualizations in add panel', async () => { + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.clickNewDashboard(); + + const exists = await dashboardAddPanel.panelAddLinkExists(LAB_VIS_NAME); + await dashboardAddPanel.closeAddPanel(); + expect(exists).to.be(false); + }); + + after(async () => { + await PageObjects.header.clickManagement(); + await PageObjects.settings.clickKibanaSettings(); + await PageObjects.settings.clearAdvancedSettings('visualize:enableLabs'); + await PageObjects.header.clickDashboard(); + }); + }); + }); + }); +} + diff --git a/test/functional/apps/dashboard/_dashboard.js b/test/functional/apps/dashboard/_dashboard.js deleted file mode 100644 index 27ba7b54d5dbd3..00000000000000 --- a/test/functional/apps/dashboard/_dashboard.js +++ /dev/null @@ -1,266 +0,0 @@ -import expect from 'expect.js'; -import { - VisualizeConstants -} from '../../../../src/core_plugins/kibana/public/visualize/visualize_constants'; - -export default function ({ getService, getPageObjects }) { - const retry = getService('retry'); - const log = getService('log'); - const dashboardVisualizations = getService('dashboardVisualizations'); - const remote = getService('remote'); - const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize', 'discover']); - const testVisualizationTitles = []; - const testVisualizationDescriptions = []; - - describe('dashboard tab', function describeIndexTests() { - before(async function () { - await PageObjects.dashboard.initTests(); - await PageObjects.dashboard.preserveCrossAppState(); - }); - - after(async function () { - // avoids any 'Object with id x not found' errors when switching tests. - await PageObjects.header.clickVisualize(); - await PageObjects.visualize.gotoLandingPage(); - await PageObjects.header.clickDashboard(); - await PageObjects.dashboard.gotoDashboardLandingPage(); - }); - - it('should be able to add visualizations to dashboard', async function addVisualizations() { - await PageObjects.dashboard.clickNewDashboard(); - await dashboardVisualizations.createAndAddTSVBVisualization('TSVB'); - await PageObjects.dashboard.addVisualizations(PageObjects.dashboard.getTestVisualizationNames()); - await dashboardVisualizations.createAndAddSavedSearch({ name: 'saved search', fields: ['bytes', 'agent'] }); - testVisualizationTitles.push('TSVB'); - testVisualizationTitles.splice(1, 0, ...PageObjects.dashboard.getTestVisualizationNames()); - testVisualizationTitles.push('saved search'); - - testVisualizationDescriptions.push(''); - testVisualizationDescriptions.splice( - 1, 0, ...PageObjects.dashboard.getTestVisualizations().map(visualization => visualization.description) - ); - testVisualizationDescriptions.push(''); - }); - - it('set the timepicker time to that which contains our test data', async function setTimepicker() { - await PageObjects.dashboard.setTimepickerInDataRange(); - }); - - it('saved search loaded with columns', async () => { - const headers = await PageObjects.discover.getColumnHeaders(); - expect(headers.length).to.be(3); - expect(headers[1]).to.be('bytes'); - expect(headers[2]).to.be('agent'); - }); - - it('should save and load dashboard', async function saveAndLoadDashboard() { - const dashboardName = 'Dashboard Test 1'; - await PageObjects.dashboard.saveDashboard(dashboardName); - await PageObjects.dashboard.gotoDashboardLandingPage(); - - await retry.try(function () { - log.debug('now re-load previously saved dashboard'); - return PageObjects.dashboard.loadSavedDashboard(dashboardName); - }); - }); - - it('should have all the expected visualizations', function checkVisualizations() { - return retry.tryForTime(10000, function () { - return PageObjects.dashboard.getPanelTitles() - .then(function (panelTitles) { - expect(panelTitles).to.eql(testVisualizationTitles); - }); - }) - .then(function () { - }); - }); - - it('retains dark theme in state', async function () { - await PageObjects.dashboard.clickEdit(); - await PageObjects.dashboard.useDarkTheme(true); - await PageObjects.header.clickVisualize(); - await PageObjects.header.clickDashboard(); - const isDarkThemeOn = await PageObjects.dashboard.isDarkThemeOn(); - expect(isDarkThemeOn).to.equal(true); - }); - - it('should be able to hide all panel titles', async function () { - await PageObjects.dashboard.checkHideTitle(); - await retry.tryForTime(10000, async function () { - const titles = await PageObjects.dashboard.getPanelTitles(); - expect(titles[0]).to.eql(''); - }); - }); - - it('should be able to unhide all panel titles', async function () { - await PageObjects.dashboard.checkHideTitle(); - await retry.tryForTime(10000, async function () { - const titles = await PageObjects.dashboard.getPanelTitles(); - expect(titles[0]).to.eql('TSVB'); - }); - }); - - describe('expanding a panel', () => { - it('hides other panels', async () => { - // Don't expand TSVB since it doesn't have the spy panel. - const panels = await PageObjects.dashboard.getDashboardPanels(); - await PageObjects.dashboard.toggleExpandPanel(panels[1]); - await retry.try(async () => { - const panels = await PageObjects.dashboard.getDashboardPanels(); - expect(panels.length).to.eql(1); - }); - }); - - it('does not show the spy pane toggle if mouse is not hovering', async () => { - // move mouse off the panel. - await PageObjects.header.clickTimepicker(); - await PageObjects.header.clickTimepicker(); - - // no spy pane without hover - const spyToggleExists = await PageObjects.visualize.getSpyToggleExists(); - expect(spyToggleExists).to.be(false); - }); - - it('shows the spy pane toggle on hover', async () => { - const panels = await PageObjects.dashboard.getDashboardPanels(); - // Simulate hover - await remote.moveMouseTo(panels[0]); - const spyToggleExists = await PageObjects.visualize.getSpyToggleExists(); - expect(spyToggleExists).to.be(true); - }); - - // This was an actual bug that appeared, where the spy pane appeared on panels after adding them, but - // disappeared when a new dashboard was opened up. - it('shows the spy pane toggle directly after opening a dashboard', async () => { - await PageObjects.dashboard.saveDashboard('spy pane test'); - await PageObjects.dashboard.gotoDashboardLandingPage(); - await PageObjects.dashboard.loadSavedDashboard('spy pane test'); - const panels = await PageObjects.dashboard.getDashboardPanels(); - // Simulate hover - await remote.moveMouseTo(panels[1]); - const spyToggleExists = await PageObjects.visualize.getSpyToggleExists(); - expect(spyToggleExists).to.be(true); - }); - - it('shows other panels after being minimized', async () => { - // Panels are all minimized on a fresh open of a dashboard, so we need to re-expand in order to then minimize. - await PageObjects.dashboard.toggleExpandPanel(); - await PageObjects.dashboard.toggleExpandPanel(); - - // Add a retry to fix https://github.com/elastic/kibana/issues/14574. Perhaps the recent changes to this - // being a CSS update is causing the UI to change slower than grabbing the panels? - retry.try(async () => { - const panels = await PageObjects.dashboard.getDashboardPanels(); - expect(panels.length).to.eql(testVisualizationTitles.length); - }); - }); - }); - - describe('embed mode', () => { - it('hides the chrome', async () => { - let isChromeVisible = await PageObjects.common.isChromeVisible(); - expect(isChromeVisible).to.be(true); - - const currentUrl = await remote.getCurrentUrl(); - const newUrl = currentUrl + '&embed=true'; - // Embed parameter only works on a hard refresh. - const useTimeStamp = true; - await remote.get(newUrl.toString(), useTimeStamp); - - await retry.try(async () => { - isChromeVisible = await PageObjects.common.isChromeVisible(); - expect(isChromeVisible).to.be(false); - }); - }); - - after(async function () { - console.log('showing chrome again'); - const currentUrl = await remote.getCurrentUrl(); - const newUrl = currentUrl.replace('&embed=true', ''); - // First use the timestamp to cause a hard refresh so the new embed parameter works correctly. - let useTimeStamp = true; - await remote.get(newUrl.toString(), useTimeStamp); - // Then get rid of the timestamp so the rest of the tests work with state and app switching. - useTimeStamp = false; - await remote.get(newUrl.toString(), useTimeStamp); - }); - }); - - describe('full screen mode', () => { - it('option not available in edit mode', async () => { - await PageObjects.dashboard.clickEdit(); - const exists = await PageObjects.dashboard.fullScreenModeMenuItemExists(); - expect(exists).to.be(false); - }); - - it('available in view mode', async () => { - await PageObjects.dashboard.saveDashboard('full screen test'); - const exists = await PageObjects.dashboard.fullScreenModeMenuItemExists(); - expect(exists).to.be(true); - }); - - it('hides the chrome', async () => { - let isChromeVisible = await PageObjects.common.isChromeVisible(); - expect(isChromeVisible).to.be(true); - - await PageObjects.dashboard.clickFullScreenMode(); - - await retry.try(async () => { - isChromeVisible = await PageObjects.common.isChromeVisible(); - expect(isChromeVisible).to.be(false); - }); - }); - - it('displays exit full screen logo button', async () => { - const exists = await PageObjects.dashboard.exitFullScreenLogoButtonExists(); - expect(exists).to.be(true); - }); - - it('displays exit full screen logo button when panel is expanded', async () => { - await PageObjects.dashboard.toggleExpandPanel(); - - const exists = await PageObjects.dashboard.exitFullScreenTextButtonExists(); - expect(exists).to.be(true); - }); - - it('exits when the text button is clicked on', async () => { - const logoButton = await PageObjects.dashboard.getExitFullScreenLogoButton(); - await remote.moveMouseTo(logoButton); - await PageObjects.dashboard.clickExitFullScreenTextButton(); - - await retry.try(async () => { - const isChromeVisible = await PageObjects.common.isChromeVisible(); - expect(isChromeVisible).to.be(true); - }); - }); - - - }); - - describe('add new visualization link', () => { - it('adds a new visualization', async () => { - await PageObjects.dashboard.clickEdit(); - await PageObjects.dashboard.clickAddVisualization(); - await PageObjects.dashboard.clickAddNewVisualizationLink(); - await PageObjects.visualize.clickAreaChart(); - await PageObjects.visualize.clickNewSearch(); - await PageObjects.visualize.saveVisualization('visualization from add new link'); - - return retry.try(async () => { - const panelCount = await PageObjects.dashboard.getPanelCount(); - expect(panelCount).to.eql(testVisualizationTitles.length + 1); - }); - }); - - it('saves the saved visualization url to the app link', async () => { - await PageObjects.header.clickVisualize(); - const currentUrl = await remote.getCurrentUrl(); - expect(currentUrl).to.contain(VisualizeConstants.EDIT_PATH); - }); - - after(async () => { - await PageObjects.header.clickDashboard(); - }); - }); - }); -} diff --git a/test/functional/apps/dashboard/_dashboard_clone.js b/test/functional/apps/dashboard/_dashboard_clone.js index d4d6bdf14acb9f..301a306563b6db 100644 --- a/test/functional/apps/dashboard/_dashboard_clone.js +++ b/test/functional/apps/dashboard/_dashboard_clone.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -42,23 +61,11 @@ export default function ({ getService, getPageObjects }) { it('and warns on duplicate name', async function () { await PageObjects.dashboard.confirmClone(); - const isConfirmOpen = await PageObjects.common.isConfirmModalOpen(); - expect(isConfirmOpen).to.equal(true); - }); - - it('preserves the original title on cancel', async function () { - await PageObjects.common.clickCancelOnModal(); - await PageObjects.dashboard.confirmClone(); - - await retry.try(async () => { - // Should see the same confirmation if the title is the same. - const isConfirmOpen = await PageObjects.common.isConfirmModalOpen(); - expect(isConfirmOpen).to.equal(true); - }); + const isWarningDisplayed = await PageObjects.dashboard.isCloneDuplicateTitleWarningDisplayed(); + expect(isWarningDisplayed).to.equal(true); }); it('and doesn\'t save', async () => { - await PageObjects.common.clickCancelOnModal(); await PageObjects.dashboard.cancelClone(); const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(dashboardName); @@ -70,7 +77,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.clickClone(); await PageObjects.dashboard.confirmClone(); - await PageObjects.common.clickConfirmOnModal(); + await PageObjects.dashboard.confirmClone(); // This is important since saving a new dashboard will cause a refresh of the page. We have to // wait till it finishes reloading or it might reload the url after simulating the diff --git a/test/functional/apps/dashboard/_dashboard_filter_bar.js b/test/functional/apps/dashboard/_dashboard_filter_bar.js index 1ef9fbed4c750f..e1f99f05b7e5f3 100644 --- a/test/functional/apps/dashboard/_dashboard_filter_bar.js +++ b/test/functional/apps/dashboard/_dashboard_filter_bar.js @@ -1,42 +1,124 @@ -import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { const dashboardExpect = getService('dashboardExpect'); - const dashboardVisualizations = getService('dashboardVisualizations'); + const dashboardAddPanel = getService('dashboardAddPanel'); const testSubjects = getService('testSubjects'); + const filterBar = getService('filterBar'); const PageObjects = getPageObjects(['dashboard', 'header', 'visualize']); - describe('dashboard filter bar', function describeIndexTests() { - before(async function () { - await PageObjects.dashboard.initTests(); - await PageObjects.dashboard.preserveCrossAppState(); - }); - - after(async function () { - // avoids any 'Object with id x not found' errors when switching tests. - await PageObjects.header.clickVisualize(); - await PageObjects.visualize.gotoLandingPage(); - await PageObjects.header.clickDashboard(); + describe('dashboard filter bar', async () => { + before(async () => { await PageObjects.dashboard.gotoDashboardLandingPage(); }); - it('Filter bar field list uses default index pattern on an empty dashboard', async () => { - await PageObjects.dashboard.clickNewDashboard(); - await testSubjects.click('addFilter'); - await dashboardExpect.fieldSuggestionIndexPatterns(['logstash-*']); + describe('Add a filter bar', async function () { + before(async () => { + await PageObjects.dashboard.gotoDashboardLandingPage(); + }); + + it('should show on an empty dashboard', async function () { + await PageObjects.dashboard.clickNewDashboard(); + const hasAddFilter = await testSubjects.exists('addFilter'); + expect(hasAddFilter).to.be(true); + }); + + it ('should continue to show for visualizations with no search source', async () => { + await dashboardAddPanel.addVisualization('Rendering-Test:-input-control'); + const hasAddFilter = await testSubjects.exists('addFilter'); + expect(hasAddFilter).to.be(true); + }); }); - // TODO: Use a data set that has more than one index pattern to better test this. - it('Filter bar field list shows index pattern of vis when one is added', async () => { - await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]); - await testSubjects.click('filterfieldSuggestionList'); - await dashboardExpect.fieldSuggestionIndexPatterns(['logstash-*']); + describe('filter editor field list', async () => { + before(async () => { + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.clickNewDashboard(); + }); + + it('uses default index pattern on an empty dashboard', async () => { + await testSubjects.click('addFilter'); + await dashboardExpect.fieldSuggestionIndexPatterns(['logstash-*']); + }); + + it('shows index pattern of vis when one is added', async () => { + await dashboardAddPanel.addVisualization('Rendering-Test:-animal-sounds-pie'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await filterBar.ensureFieldEditorModalIsClosed(); + await testSubjects.click('addFilter'); + await dashboardExpect.fieldSuggestionIndexPatterns(['animals-*']); + }); + + it('works when a vis with no index pattern is added', async () => { + await dashboardAddPanel.addVisualization('Rendering-Test:-markdown'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await filterBar.ensureFieldEditorModalIsClosed(); + await testSubjects.click('addFilter'); + await dashboardExpect.fieldSuggestionIndexPatterns(['animals-*']); + }); }); - it('Filter bar field list works when a vis with no index pattern is added', async () => { - await dashboardVisualizations.createAndAddMarkdown({ name: 'markdown', markdown: 'hi ima markdown' }); - await testSubjects.click('addFilter'); - await dashboardExpect.fieldSuggestionIndexPatterns(['logstash-*']); + describe('filter pills', async function () { + before(async () => { + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.clickNewDashboard(); + await PageObjects.dashboard.setTimepickerInDataRange(); + }); + + it('are not selected by default', async function () { + const filters = await PageObjects.dashboard.getFilters(1000); + expect(filters.length).to.equal(0); + }); + + it('are added when a pie chart slice is clicked', async function () { + await dashboardAddPanel.addVisualization('Rendering Test: pie'); + await PageObjects.dashboard.waitForRenderComplete(); + await PageObjects.dashboard.filterOnPieSlice('4,886'); + const filters = await PageObjects.dashboard.getFilters(); + expect(filters.length).to.equal(1); + + await dashboardExpect.pieSliceCount(1); + }); + + it('are preserved after saving a dashboard', async () => { + await PageObjects.dashboard.saveDashboard('with filters'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const filters = await PageObjects.dashboard.getFilters(); + expect(filters.length).to.equal(1); + + await dashboardExpect.pieSliceCount(1); + }); + + it('are preserved after opening a dashboard saved with filters', async () => { + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.loadSavedDashboard('with filters'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const filters = await PageObjects.dashboard.getFilters(); + expect(filters.length).to.equal(1); + + await dashboardExpect.pieSliceCount(1); + }); }); }); } diff --git a/test/functional/apps/dashboard/_dashboard_filtering.js b/test/functional/apps/dashboard/_dashboard_filtering.js new file mode 100644 index 00000000000000..a316e1cee9e119 --- /dev/null +++ b/test/functional/apps/dashboard/_dashboard_filtering.js @@ -0,0 +1,219 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +/** + * Test the querying capabilities of dashboard, and make sure visualizations show the expected results, especially + * with nested queries and filters on the visualizations themselves. + */ +export default function ({ getService, getPageObjects }) { + const dashboardExpect = getService('dashboardExpect'); + const queryBar = getService('queryBar'); + const dashboardAddPanel = getService('dashboardAddPanel'); + const testSubjects = getService('testSubjects'); + const filterBar = getService('filterBar'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const PageObjects = getPageObjects(['dashboard', 'header', 'visualize']); + + describe('dashboard filtering', async () => { + before(async () => { + await PageObjects.dashboard.gotoDashboardLandingPage(); + }); + + describe('adding a filter that excludes all data', async () => { + before(async () => { + await PageObjects.dashboard.clickNewDashboard(); + await PageObjects.dashboard.setTimepickerInDataRange(); + await dashboardAddPanel.addEveryVisualization('"Filter Bytes Test"'); + await dashboardAddPanel.addEverySavedSearch('"Filter Bytes Test"'); + await dashboardAddPanel.closeAddPanel(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + await filterBar.addFilter('bytes', 'is', '12345678'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + }); + + it('filters on pie charts', async () => { + await dashboardExpect.pieSliceCount(0); + }); + + it('area, bar and heatmap charts filtered', async () => { + await dashboardExpect.seriesElementCount(0); + }); + + it('data tables are filtered', async () => { + await dashboardExpect.dataTableRowCount(0); + }); + + it('goal and guages are filtered', async () => { + await dashboardExpect.goalAndGuageLabelsExist(['0', '0%']); + }); + + it('tsvb time series shows no data message', async () => { + expect(await testSubjects.exists('noTSVBDataMessage')).to.be(true); + await dashboardExpect.tsvbTimeSeriesLegendCount(0); + }); + + it('metric value shows no data', async () => { + await dashboardExpect.metricValuesExist(['-']); + }); + + it('tag cloud values are filtered', async () => { + await dashboardExpect.emptyTagCloudFound(); + }); + + it('tsvb metric is filtered', async () => { + await dashboardExpect.tsvbMetricValuesExist(['0 custom template']); + }); + + it('tsvb top n is filtered', async () => { + await dashboardExpect.tsvbTopNValuesExist(['0', '0']); + }); + + it('saved search is filtered', async () => { + await dashboardExpect.savedSearchRowCount(0); + }); + + it('timelion is filtered', async () => { + await dashboardExpect.timelionLegendCount(0); + }); + + it('vega is filtered', async () => { + await dashboardExpect.vegaTextsDoNotExist(['5,000']); + }); + }); + + + describe('disabling a filter unfilters the data on', async () => { + before(async () => { + await testSubjects.click('disableFilter-bytes'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + }); + + it('pie charts', async () => { + await dashboardExpect.pieSliceCount(5); + }); + + it('area, bar and heatmap charts', async () => { + await dashboardExpect.seriesElementCount(3); + }); + + it('data tables', async () => { + await dashboardExpect.dataTableRowCount(10); + }); + + it('goal and guages', async () => { + await dashboardExpect.goalAndGuageLabelsExist(['40%', '7,544']); + }); + + it('tsvb time series', async () => { + expect(await testSubjects.exists('noTSVBDataMessage')).to.be(false); + await dashboardExpect.tsvbTimeSeriesLegendCount(10); + }); + + it('metric value', async () => { + await dashboardExpect.metricValuesExist(['101']); + }); + + it('tag cloud', async () => { + await dashboardExpect.tagCloudWithValuesFound(['9,972', '4,886', '1,944', '9,025']); + }); + + it('tsvb metric', async () => { + await dashboardExpect.tsvbMetricValuesExist(['50,465 custom template']); + }); + + it('tsvb top n', async () => { + await dashboardExpect.tsvbTopNValuesExist(['6,308.13', '6,308.13']); + }); + + it('tsvb markdown', async () => { + await dashboardExpect.tsvbMarkdownWithValuesExists(['7,209.29']); + }); + + it('saved searches', async () => { + await dashboardExpect.savedSearchRowCount(1); + }); + + it('vega', async () => { + await dashboardExpect.vegaTextsExist(['5,000']); + }); + }); + + describe('nested filtering', async () => { + before(async () => { + await PageObjects.dashboard.gotoDashboardLandingPage(); + }); + + it('visualization saved with a query filters data', async () => { + await PageObjects.dashboard.clickNewDashboard(); + await PageObjects.dashboard.setTimepickerInDataRange(); + + await dashboardAddPanel.addVisualization('Rendering-Test:-animal-sounds-pie'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + await dashboardExpect.pieSliceCount(5); + + await dashboardPanelActions.clickEdit(); + await queryBar.setQuery('weightLbs:>50'); + await queryBar.submitQuery(); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + await dashboardExpect.pieSliceCount(3); + + await PageObjects.visualize.saveVisualization('Rendering-Test:-animal-sounds-pie'); + await PageObjects.header.clickDashboard(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + await dashboardExpect.pieSliceCount(3); + }); + + it('Nested visualization filter pills filters data as expected', async () => { + await dashboardPanelActions.clickEdit(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + await PageObjects.dashboard.filterOnPieSlice('grr'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await dashboardExpect.pieSliceCount(1); + + await PageObjects.visualize.saveVisualization('animal sounds pie'); + await PageObjects.header.clickDashboard(); + + await dashboardExpect.pieSliceCount(1); + }); + + it('Pie chart linked to saved search filters data', async () => { + await dashboardAddPanel.addVisualization('Filter Test: animals: linked to search with filter'); + await dashboardExpect.pieSliceCount(3); + }); + + it('Pie chart linked to saved search filters shows no data with conflicting dashboard query', async () => { + await queryBar.setQuery('weightLbs:<40'); + await queryBar.submitQuery(); + await PageObjects.dashboard.waitForRenderComplete(); + + await dashboardExpect.pieSliceCount(0); + }); + }); + }); +} diff --git a/test/functional/apps/dashboard/_dashboard_grid.js b/test/functional/apps/dashboard/_dashboard_grid.js index a8264b9fd1d2c1..933d40bc390fcc 100644 --- a/test/functional/apps/dashboard/_dashboard_grid.js +++ b/test/functional/apps/dashboard/_dashboard_grid.js @@ -1,51 +1,41 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { - const find = getService('find'); const remote = getService('remote'); - const PageObjects = getPageObjects(['dashboard', 'header', 'common']); - - const VIS_TITLES = [ - PageObjects.dashboard.getTestVisualizationNames()[0], - PageObjects.dashboard.getTestVisualizationNames()[1], - PageObjects.dashboard.getTestVisualizationNames()[2], - ]; - - // Order returned by find.allByCssSelector is not guaranteed and can change based on timing - // Use this function to avoid looking for elements by hard-coded array index. - const getPanelTitleElement = async (title) => { - const panelTitleElements = await find.allByCssSelector('.panel-title'); - for (let i = 0; i < panelTitleElements.length; i++) { - const panelText = await panelTitleElements[i].getVisibleText(); - if (panelText === title) { - return panelTitleElements[i]; - } - } - - throw new Error(`Unable to find panel with title: "${title}"`); - }; + const dashboardPanelActions = getService('dashboardPanelActions'); + const PageObjects = getPageObjects(['dashboard']); describe('dashboard grid', () => { - before(async () => { - return PageObjects.dashboard.initTests(); - }); - - after(async () => { - // avoids any 'Object with id x not found' errors when switching tests. - await PageObjects.header.clickDashboard(); await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.loadSavedDashboard('few panels'); + await PageObjects.dashboard.clickEdit(); }); describe('move panel', () => { // Specific test after https://github.com/elastic/kibana/issues/14764 fix it('Can move panel from bottom to top row', async () => { - await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.addVisualizations(VIS_TITLES); - - const lastVisTitle = VIS_TITLES[VIS_TITLES.length - 1]; - - const panelTitleBeforeMove = await getPanelTitleElement(lastVisTitle); + const lastVisTitle = 'Rendering Test: datatable'; + const panelTitleBeforeMove = await dashboardPanelActions.getPanelHeading(lastVisTitle); const position1 = await panelTitleBeforeMove.getPosition(); remote @@ -54,7 +44,7 @@ export default function ({ getService, getPageObjects }) { .moveMouseTo(null, -20, -450) .releaseMouseButton(); - const panelTitleAfterMove = await getPanelTitleElement(lastVisTitle); + const panelTitleAfterMove = await dashboardPanelActions.getPanelHeading(lastVisTitle); const position2 = await panelTitleAfterMove.getPosition(); expect(position1.y).to.be.greaterThan(position2.y); diff --git a/test/functional/apps/dashboard/_dashboard_listing.js b/test/functional/apps/dashboard/_dashboard_listing.js index bd2506ea8513a3..208ac30e83c796 100644 --- a/test/functional/apps/dashboard/_dashboard_listing.js +++ b/test/functional/apps/dashboard/_dashboard_listing.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -42,8 +61,8 @@ export default function ({ getService, getPageObjects }) { describe('delete', async function () { it('default confirm action is cancel', async function () { - await PageObjects.dashboard.searchForDashboardWithName(''); - await PageObjects.dashboard.clickListItemCheckbox(); + await PageObjects.dashboard.searchForDashboardWithName(dashboardName); + await PageObjects.dashboard.checkDashboardListingSelectAllCheckbox(); await PageObjects.dashboard.clickDeleteSelectedDashboards(); await PageObjects.common.pressEnterKey(); @@ -56,7 +75,7 @@ export default function ({ getService, getPageObjects }) { }); it('succeeds on confirmation press', async function () { - await PageObjects.dashboard.clickListItemCheckbox(); + await PageObjects.dashboard.checkDashboardListingSelectAllCheckbox(); await PageObjects.dashboard.clickDeleteSelectedDashboards(); await PageObjects.common.clickConfirmOnModal(); @@ -69,7 +88,7 @@ export default function ({ getService, getPageObjects }) { describe('search', function () { before(async () => { await PageObjects.dashboard.clearSearchValue(); - await PageObjects.dashboard.clickCreateDashboardPrompt(); + await PageObjects.dashboard.clickNewDashboard(); await PageObjects.dashboard.saveDashboard('Two Words'); }); diff --git a/test/functional/apps/dashboard/_dashboard_options.js b/test/functional/apps/dashboard/_dashboard_options.js new file mode 100644 index 00000000000000..c3e4587feb8b32 --- /dev/null +++ b/test/functional/apps/dashboard/_dashboard_options.js @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +export default function ({ getService, getPageObjects }) { + const retry = getService('retry'); + const PageObjects = getPageObjects(['dashboard']); + + describe('dashboard data-shared attributes', async () => { + let originalTitles = []; + + before(async () => { + await PageObjects.dashboard.loadSavedDashboard('few panels'); + await PageObjects.dashboard.clickEdit(); + originalTitles = await PageObjects.dashboard.getPanelTitles(); + }); + + it('should be able to hide all panel titles', async () => { + await PageObjects.dashboard.checkHideTitle(); + await retry.try(async () => { + const titles = await PageObjects.dashboard.getPanelTitles(); + expect(titles[0]).to.eql(''); + }); + }); + + it('should be able to unhide all panel titles', async () => { + await PageObjects.dashboard.checkHideTitle(); + await retry.try(async () => { + const titles = await PageObjects.dashboard.getPanelTitles(); + expect(titles[0]).to.eql(originalTitles[0]); + }); + }); + }); +} diff --git a/test/functional/apps/dashboard/_dashboard_queries.js b/test/functional/apps/dashboard/_dashboard_queries.js deleted file mode 100644 index e8a55148d8cd9e..00000000000000 --- a/test/functional/apps/dashboard/_dashboard_queries.js +++ /dev/null @@ -1,152 +0,0 @@ -import expect from 'expect.js'; - -import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; - -/** - * Test the querying capabilities of dashboard, and make sure visualizations show the expected results, especially - * with nested queries and filters on the visualizations themselves. - */ -export default function ({ getService, getPageObjects }) { - const dashboardExpect = getService('dashboardExpect'); - const dashboardVisualizations = getService('dashboardVisualizations'); - const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['dashboard', 'header', 'visualize']); - - describe('dashboard queries', function describeIndexTests() { - before(async function () { - await PageObjects.dashboard.initTests(); - await PageObjects.dashboard.preserveCrossAppState(); - }); - - after(async function () { - // avoids any 'Object with id x not found' errors when switching tests. - await PageObjects.header.clickVisualize(); - await PageObjects.visualize.gotoLandingPage(); - await PageObjects.header.clickDashboard(); - await PageObjects.dashboard.gotoDashboardLandingPage(); - }); - - it('Nested visualization query filters data as expected', async () => { - await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInDataRange(); - - await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]); - await PageObjects.dashboard.clickEditVisualization(); - await PageObjects.dashboard.setQuery('memory:<80000'); - await PageObjects.dashboard.clickFilterButton(); - await PageObjects.header.waitUntilLoadingHasFinished(); - await dashboardExpect.pieSliceCount(2); - - await PageObjects.visualize.saveVisualization(PIE_CHART_VIS_NAME); - await PageObjects.header.clickDashboard(); - - await dashboardExpect.pieSliceCount(2); - }); - - it('Nested visualization filter pills filters data as expected', async () => { - await PageObjects.dashboard.clickEditVisualization(); - await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.dashboard.waitForRenderComplete(); - await PageObjects.dashboard.filterOnPieSlice(); - await PageObjects.header.waitUntilLoadingHasFinished(); - await dashboardExpect.pieSliceCount(1); - - await PageObjects.visualize.saveVisualization(PIE_CHART_VIS_NAME); - await PageObjects.header.clickDashboard(); - - await dashboardExpect.pieSliceCount(1); - }); - - it('Pie chart attached to saved search filters data as expected', async () => { - await dashboardVisualizations.createAndAddSavedSearch({ - name: 'bytes < 90', - query: 'bytes:<90', - fields: ['bytes'] - }); - - await PageObjects.header.clickDashboard(); - await PageObjects.dashboard.gotoDashboardLandingPage(); - await PageObjects.dashboard.clickNewDashboard(); - - await PageObjects.dashboard.clickAddVisualization(); - await PageObjects.dashboard.clickAddNewVisualizationLink(); - await PageObjects.visualize.clickPieChart(); - await PageObjects.visualize.selectSearch('bytes < 90'); - await PageObjects.visualize.clickBucket('Split Slices'); - await PageObjects.visualize.selectAggregation('Terms'); - await PageObjects.visualize.selectField('memory'); - await PageObjects.visualize.clickGo(); - await PageObjects.visualize.saveVisualization('memory with bytes < 90 pie'); - - await dashboardExpect.pieSliceCount(3); - }); - - it('Pie chart attached to saved search filters shows no data with conflicting dashboard query', async () => { - await PageObjects.dashboard.setQuery('bytes:>100'); - await PageObjects.dashboard.clickFilterButton(); - await PageObjects.header.waitUntilLoadingHasFinished(); - - await dashboardExpect.pieSliceCount(0); - }); - - describe('visualizations without SearchSource', async function () { - before(async () => { - await PageObjects.dashboard.gotoDashboardLandingPage(); - await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.addVisualizations(['Visualization InputControl']); - }); - - it(`should have filter bar with 'Add a filter'`, async function () { - const hasAddFilter = await testSubjects.exists('addFilter'); - expect(hasAddFilter).to.be(true); - }); - }); - - describe('filters', async function () { - before(async () => { - await PageObjects.dashboard.gotoDashboardLandingPage(); - await PageObjects.dashboard.clickNewDashboard(); - }); - - it('are not selected by default', async function () { - const filters = await PageObjects.dashboard.getFilters(1000); - expect(filters.length).to.equal(0); - }); - - it('are added when a pie chart slice is clicked', async function () { - await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]); - // Click events not added until visualization is finished rendering. - // See https://github.com/elastic/kibana/issues/15480#issuecomment-350195245 for more info on why - // this is necessary. - await PageObjects.dashboard.waitForRenderComplete(); - await PageObjects.dashboard.filterOnPieSlice(); - const filters = await PageObjects.dashboard.getFilters(); - expect(filters.length).to.equal(1); - - await dashboardExpect.pieSliceCount(1); - }); - - it('are preserved after saving a dashboard', async () => { - await PageObjects.dashboard.saveDashboard('with filters'); - await PageObjects.header.waitUntilLoadingHasFinished(); - - const filters = await PageObjects.dashboard.getFilters(); - expect(filters.length).to.equal(1); - - await dashboardExpect.pieSliceCount(1); - }); - - it('are preserved after opening a dashboard saved with filters', async () => { - await PageObjects.dashboard.gotoDashboardLandingPage(); - await PageObjects.dashboard.loadSavedDashboard('with filters'); - await PageObjects.header.waitUntilLoadingHasFinished(); - - const filters = await PageObjects.dashboard.getFilters(); - expect(filters.length).to.equal(1); - - await dashboardExpect.pieSliceCount(1); - }); - }); - - }); -} diff --git a/test/functional/apps/dashboard/_dashboard_save.js b/test/functional/apps/dashboard/_dashboard_save.js index b1f6f42d8d08a1..77d33e0d16d6b4 100644 --- a/test/functional/apps/dashboard/_dashboard_save.js +++ b/test/functional/apps/dashboard/_dashboard_save.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -56,7 +75,7 @@ export default function ({ getService, getPageObjects }) { it('Does not warn when you save an existing dashboard with the title it already has, and that title is a duplicate', async function () { await PageObjects.dashboard.selectDashboard(dashboardName); - await PageObjects.header.isGlobalLoadingIndicatorHidden(); + await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); await PageObjects.dashboard.clickEdit(); await PageObjects.dashboard.saveDashboard(dashboardName); diff --git a/test/functional/apps/dashboard/_dashboard_shared_attributes.js b/test/functional/apps/dashboard/_dashboard_shared_attributes.js deleted file mode 100644 index 6c105b75c93741..00000000000000 --- a/test/functional/apps/dashboard/_dashboard_shared_attributes.js +++ /dev/null @@ -1,98 +0,0 @@ -import expect from 'expect.js'; - -export default function ({ getService, getPageObjects }) { - const retry = getService('retry'); - const log = getService('log'); - const dashboardVisualizations = getService('dashboardVisualizations'); - const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['dashboard']); - const testVisualizationTitles = [PageObjects.dashboard.getTestVisualizationNames()[0], 'saved search']; - const testVisualizationDescriptions = [PageObjects.dashboard.getTestVisualizationDescriptions()[0], '']; - - describe('dashboard shared attributes', function describeIndexTests() { - before(async function () { - await PageObjects.dashboard.initTests(); - await PageObjects.dashboard.preserveCrossAppState(); - await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.addVisualizations([PageObjects.dashboard.getTestVisualizationNames()[0]]); - await dashboardVisualizations.createAndAddSavedSearch({ name: 'saved search', fields: ['bytes', 'agent'] }); - }); - - it('should have data-shared-items-count set to the number of visualizations', function checkSavedItemsCount() { - return retry.tryForTime(10000, () => PageObjects.dashboard.getSharedItemsCount()) - .then(function (count) { - log.info('data-shared-items-count = ' + count); - expect(count).to.eql(testVisualizationTitles.length); - }); - }); - - it('should have panels with expected data-shared-item title and description', async () => { - await retry.try(async () => { - await PageObjects.dashboard.getPanelSharedItemData() - .then(function (data) { - expect(data.map(item => item.title)).to.eql(testVisualizationTitles); - expect(data.map(item => item.description)).to.eql(testVisualizationDescriptions); - }); - }); - }); - - it('data-shared-item title should update a viz when using a custom panel title', async () => { - const CUSTOM_VIS_TITLE = 'ima custom title for a vis!'; - await PageObjects.dashboard.setCustomPanelTitle(CUSTOM_VIS_TITLE); - await retry.try(async () => { - const sharedData = await PageObjects.dashboard.getPanelSharedItemData(); - const foundSharedItemTitle = !!sharedData.find(item => { - return item.title === CUSTOM_VIS_TITLE; - }); - expect(foundSharedItemTitle).to.be(true); - }); - }); - - it('data-shared-item title is cleared with an empty panel title string', async () => { - await PageObjects.dashboard.setCustomPanelTitle('h\b'); - await retry.try(async () => { - const sharedData = await PageObjects.dashboard.getPanelSharedItemData(); - const foundSharedItemTitle = !!sharedData.find(item => { - return item.title === ''; - }); - expect(foundSharedItemTitle).to.be(true); - }); - }); - - it('data-shared-item title can be reset', async () => { - await PageObjects.dashboard.resetCustomPanelTitle(); - await retry.try(async () => { - const sharedData = await PageObjects.dashboard.getPanelSharedItemData(); - const foundOriginalSharedItemTitle = !!sharedData.find(item => { - return item.title === testVisualizationTitles[0]; - }); - expect(foundOriginalSharedItemTitle).to.be(true); - }); - }); - - it('data-shared-item title should update a saved search when using a custom panel title', async () => { - const CUSTOM_SEARCH_TITLE = 'ima custom title for a search!'; - const panels = await PageObjects.dashboard.getDashboardPanels(); - // The reverse is only to take advantage of the fact that the saved search is last at the time of writing this - // test which speeds things up. - const searchPanel = await Promise.race(panels.map(async panel => { - return new Promise(async resolve => { - const savedSearchPanel = await testSubjects.descendantExists('embeddedSavedSearchDocTable', panel); - if (savedSearchPanel) { - resolve(panel); - } - }); - })); - await PageObjects.dashboard.setCustomPanelTitle(CUSTOM_SEARCH_TITLE, searchPanel); - await retry.try(async () => { - const sharedData = await PageObjects.dashboard.getPanelSharedItemData(); - const foundSharedItemTitle = !!sharedData.find(item => { - return item.title === CUSTOM_SEARCH_TITLE; - }); - console.log('foundSharedItemTitle: ' + foundSharedItemTitle); - - expect(foundSharedItemTitle).to.be(true); - }); - }); - }); -} diff --git a/test/functional/apps/dashboard/_dashboard_snapshots.js b/test/functional/apps/dashboard/_dashboard_snapshots.js index 722f6e3812d5e6..c89768fc44cb5d 100644 --- a/test/functional/apps/dashboard/_dashboard_snapshots.js +++ b/test/functional/apps/dashboard/_dashboard_snapshots.js @@ -1,76 +1,85 @@ -import expect from 'expect.js'; - -import { AREA_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import expect from 'expect.js'; export default function ({ getService, getPageObjects, updateBaselines }) { - const dashboardVisualizations = getService('dashboardVisualizations'); const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'common']); const screenshot = getService('screenshots'); const remote = getService('remote'); - const testSubjects = getService('testSubjects'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const dashboardAddPanel = getService('dashboardAddPanel'); describe('dashboard snapshots', function describeIndexTests() { before(async function () { - await PageObjects.dashboard.initTests(); - await PageObjects.dashboard.preserveCrossAppState(); + // We use a really small window to minimize differences across os's and browsers. await remote.setWindowSize(1000, 500); }); after(async function () { - // avoids any 'Object with id x not found' errors when switching tests. - await PageObjects.header.clickVisualize(); - await PageObjects.visualize.gotoLandingPage(); - await PageObjects.header.clickDashboard(); - await PageObjects.dashboard.gotoDashboardLandingPage(); + await remote.setWindowSize(1300, 900); }); - // This one won't work because of https://github.com/elastic/kibana/issues/15501. See if we can get it to work - // once TSVB has timezone support. + // Skip until https://github.com/elastic/kibana/issues/19471 is fixed it.skip('compare TSVB snapshot', async () => { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInDataRange(); - await dashboardVisualizations.createAndAddTSVBVisualization('TSVB'); - await testSubjects.click('toastCloseButton'); + await PageObjects.dashboard.setTimepickerInLogstashDataRange(); + await dashboardAddPanel.addVisualization('Rendering Test: tsvb-ts'); + await PageObjects.common.closeToast(); await PageObjects.dashboard.saveDashboard('tsvb'); - await testSubjects.click('saveDashboardSuccess toastCloseButton'); + await PageObjects.common.closeToast(); await PageObjects.dashboard.clickFullScreenMode(); - await PageObjects.dashboard.toggleExpandPanel(); + await dashboardPanelActions.toggleExpandPanel(); await PageObjects.dashboard.waitForRenderComplete(); + // Render complete flag doesn't handle resizes from expanding. + await PageObjects.common.sleep(2000); const percentSimilar = await screenshot.compareAgainstBaseline('tsvb_dashboard', updateBaselines); await PageObjects.dashboard.clickExitFullScreenLogoButton(); - expect(percentSimilar).to.be(0); + expect(percentSimilar).to.be.lessThan(0.05); }); it('compare area chart snapshot', async () => { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInDataRange(); - await PageObjects.dashboard.addVisualizations([AREA_CHART_VIS_NAME]); - await testSubjects.click('addVisualizationToDashboardSuccess toastCloseButton'); - + await PageObjects.dashboard.setTimepickerInLogstashDataRange(); + await dashboardAddPanel.addVisualization('Rendering Test: area with not filter'); + await PageObjects.common.closeToast(); await PageObjects.dashboard.saveDashboard('area'); - await testSubjects.click('saveDashboardSuccess toastCloseButton'); + await PageObjects.common.closeToast(); await PageObjects.dashboard.clickFullScreenMode(); - await PageObjects.dashboard.toggleExpandPanel(); + await dashboardPanelActions.toggleExpandPanel(); await PageObjects.dashboard.waitForRenderComplete(); - // The need for this should have been removed with https://github.com/elastic/kibana/pull/15574 but the - // test failed when removed because the visualization hadn't settled. - await PageObjects.common.sleep(1000); - + // Render complete flag doesn't handle resizes from expanding. + await PageObjects.common.sleep(2000); const percentSimilar = await screenshot.compareAgainstBaseline('area_chart', updateBaselines); await PageObjects.dashboard.clickExitFullScreenLogoButton(); - // Testing some OS/browser differnces were shown to cause .009 percent difference. + // Testing some OS/browser differences were shown to cause .009 percent difference. expect(percentSimilar).to.be.lessThan(0.05); }); }); diff --git a/test/functional/apps/dashboard/_dashboard_state.js b/test/functional/apps/dashboard/_dashboard_state.js index f431a540b2668e..662ba77dfa75f1 100644 --- a/test/functional/apps/dashboard/_dashboard_state.js +++ b/test/functional/apps/dashboard/_dashboard_state.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { PIE_CHART_VIS_NAME, AREA_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; @@ -9,7 +28,10 @@ export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['dashboard', 'visualize', 'header', 'discover']); const testSubjects = getService('testSubjects'); const remote = getService('remote'); + const queryBar = getService('queryBar'); const retry = getService('retry'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const dashboardAddPanel = getService('dashboardAddPanel'); describe('dashboard state', function describeIndexTests() { before(async function () { @@ -25,18 +47,15 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); - await PageObjects.dashboard.addVisualizations([AREA_CHART_VIS_NAME]); + await dashboardAddPanel.addVisualization(AREA_CHART_VIS_NAME); await PageObjects.dashboard.saveDashboard('Overridden colors'); await PageObjects.dashboard.clickEdit(); - // Opening legend colors has been flaky. - retry.try(async () => { - await PageObjects.visualize.clickLegendOption('Count'); - await PageObjects.visualize.selectNewLegendColorChoice('#EA6460'); - }); + await PageObjects.visualize.openLegendOptionColors('Count'); + await PageObjects.visualize.selectNewLegendColorChoice('#EA6460'); await PageObjects.dashboard.saveDashboard('Overridden colors'); @@ -51,7 +70,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.header.clickDiscover(); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); await PageObjects.discover.clickFieldListItemAdd('bytes'); await PageObjects.discover.saveSearch('my search'); await PageObjects.header.waitUntilLoadingHasFinished(); @@ -59,7 +78,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.header.clickDashboard(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.addSavedSearch('my search'); + await dashboardAddPanel.addSavedSearch('my search'); await PageObjects.dashboard.saveDashboard('No local edits'); const inViewMode = await testSubjects.exists('dashboardEditMode'); @@ -101,9 +120,9 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); - await PageObjects.dashboard.addVisualizations(['Visualization TileMap']); + await dashboardAddPanel.addVisualization('Visualization TileMap'); await PageObjects.dashboard.saveDashboard('No local edits'); await testSubjects.moveMouseTo('dashboardPanel'); @@ -113,7 +132,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.closeSpyPanel(); await PageObjects.dashboard.clickEdit(); - await PageObjects.dashboard.clickEditVisualization(); + await dashboardPanelActions.clickEdit(); await PageObjects.visualize.clickMapZoomIn(); await PageObjects.visualize.clickMapZoomIn(); @@ -129,28 +148,35 @@ export default function ({ getService, getPageObjects }) { const changedTileMapData = await PageObjects.visualize.getDataTableData(); await testSubjects.moveMouseTo('dashboardPanel'); await PageObjects.visualize.closeSpyPanel(); - expect(changedTileMapData.length).to.not.equal(tileMapData.length); }); + it('retains dark theme', async function () { + await PageObjects.dashboard.useDarkTheme(true); + await PageObjects.header.clickVisualize(); + await PageObjects.header.clickDashboard(); + const isDarkThemeOn = await PageObjects.dashboard.isDarkThemeOn(); + expect(isDarkThemeOn).to.equal(true); + }); + describe('Directly modifying url updates dashboard state', () => { it('for query parameter', async function () { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - const currentQuery = await PageObjects.dashboard.getQuery(); + const currentQuery = await queryBar.getQueryString(); expect(currentQuery).to.equal(''); const currentUrl = await remote.getCurrentUrl(); const newUrl = currentUrl.replace('query:%27%27', 'query:%27hi%27'); // Don't add the timestamp to the url or it will cause a hard refresh and we want to test a // soft refresh. await remote.get(newUrl.toString(), false); - const newQuery = await PageObjects.dashboard.getQuery(); + const newQuery = await queryBar.getQueryString(); expect(newQuery).to.equal('hi'); }); it('for panel size parameters', async function () { - await PageObjects.dashboard.addVisualization(PIE_CHART_VIS_NAME); + await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); const currentUrl = await remote.getCurrentUrl(); const currentPanelDimensions = await PageObjects.dashboard.getPanelDimensions(); const newUrl = currentUrl.replace(`w:${DEFAULT_PANEL_WIDTH}`, `w:${DEFAULT_PANEL_WIDTH * 2}`); @@ -160,12 +186,10 @@ export default function ({ getService, getPageObjects }) { if (newPanelDimensions.length < 0) { throw new Error('No panel dimensions...'); } - // Some margin of error is allowed (I've noticed it being off by one pixel which probably something to do - // with an odd width and dividing by two), but due to https://github.com/elastic/kibana/issues/14542 I'm - // adding more margin of error than should be necessary. That issue looks legit, but because I can't - // repro locally, I don't have a quick solution aside from increasing this margin error, for getting the - // build to pass consistently again. - const marginOfError = 20; + + await PageObjects.dashboard.waitForRenderComplete(); + // Add a "margin" of error - because of page margins, it won't be a straight doubling of width. + const marginOfError = 10; expect(newPanelDimensions[0].width).to.be.lessThan(currentPanelDimensions[0].width * 2 + marginOfError); expect(newPanelDimensions[0].width).to.be.greaterThan(currentPanelDimensions[0].width * 2 - marginOfError); }); @@ -184,8 +208,8 @@ export default function ({ getService, getPageObjects }) { describe('for embeddable config color parameters on a visualization', () => { it('updates a pie slice color on a soft refresh', async function () { - await PageObjects.dashboard.addVisualization(PIE_CHART_VIS_NAME); - await PageObjects.visualize.clickLegendOption('80,000'); + await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); + await PageObjects.visualize.openLegendOptionColors('80,000'); await PageObjects.visualize.selectNewLegendColorChoice('#F9D9F9'); const currentUrl = await remote.getCurrentUrl(); const newUrl = currentUrl.replace('F9D9F9', 'FFFFFF'); diff --git a/test/functional/apps/dashboard/_dashboard_time.js b/test/functional/apps/dashboard/_dashboard_time.js index 8e17c3896435d3..d05bee8d853edf 100644 --- a/test/functional/apps/dashboard/_dashboard_time.js +++ b/test/functional/apps/dashboard/_dashboard_time.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; const dashboardName = 'Dashboard Test Time'; @@ -8,7 +27,7 @@ const toTime = '2015-09-23 18:31:44.000'; export default function ({ getPageObjects }) { const PageObjects = getPageObjects(['dashboard', 'header']); - describe('dashboard time', function dashboardSaveWithTime() { + describe('dashboard time', () => { before(async function () { await PageObjects.dashboard.initTests(); await PageObjects.dashboard.preserveCrossAppState(); @@ -18,15 +37,15 @@ export default function ({ getPageObjects }) { await PageObjects.dashboard.gotoDashboardLandingPage(); }); - describe('dashboard without stored timed', async function () { - it('is saved', async function () { + describe('dashboard without stored timed', () => { + it('is saved', async () => { await PageObjects.dashboard.clickNewDashboard(); await PageObjects.dashboard.addVisualizations([PageObjects.dashboard.getTestVisualizationNames()[0]]); const isDashboardSaved = await PageObjects.dashboard.saveDashboard(dashboardName, { storeTimeWithDashboard: false }); expect(isDashboardSaved).to.eql(true); }); - it('Does not set the time picker on open', async function () { + it('Does not set the time picker on open', async () => { await PageObjects.header.setAbsoluteRange(fromTime, toTime); await PageObjects.dashboard.loadSavedDashboard(dashboardName); diff --git a/test/functional/apps/dashboard/_dashboard_time_picker.js b/test/functional/apps/dashboard/_dashboard_time_picker.js index da70f9369bce6c..f79b3af22e5750 100644 --- a/test/functional/apps/dashboard/_dashboard_time_picker.js +++ b/test/functional/apps/dashboard/_dashboard_time_picker.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; export default function ({ getService, getPageObjects }) { @@ -24,7 +43,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]); await dashboardExpect.pieSliceCount(0); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); await dashboardExpect.pieSliceCount(10); }); diff --git a/test/functional/apps/dashboard/_data_shared_attributes.js b/test/functional/apps/dashboard/_data_shared_attributes.js new file mode 100644 index 00000000000000..0a50ed3db398ac --- /dev/null +++ b/test/functional/apps/dashboard/_data_shared_attributes.js @@ -0,0 +1,104 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +export default function ({ getService, getPageObjects }) { + const retry = getService('retry'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const PageObjects = getPageObjects(['dashboard']); + + describe('dashboard data-shared attributes', function describeIndexTests() { + let originalPanelTitles; + + before(async () => { + await PageObjects.dashboard.loadSavedDashboard('dashboard with everything'); + }); + + it('should have data-shared-items-count set to the number of embeddables on the dashboard', async () => { + await retry.try(async () => { + const sharedItemsCount = await PageObjects.dashboard.getSharedItemsCount(); + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(sharedItemsCount).to.eql(panelCount); + }); + }); + + it('should have panels with expected data-shared-item title', async () => { + await retry.try(async () => { + const sharedData = await PageObjects.dashboard.getPanelSharedItemData(); + originalPanelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(sharedData.map(item => item.title)).to.eql(originalPanelTitles); + }); + }); + + it('data shared item container data has description and title set', async () => { + const sharedContainerData = await PageObjects.dashboard.getSharedContainerData(); + expect(sharedContainerData.title).to.be('dashboard with everything'); + expect(sharedContainerData.description).to.be( + 'I have one of every visualization type since the last time I was created!'); + }); + + it('data-shared-item title should update a viz when using a custom panel title', async () => { + await PageObjects.dashboard.clickEdit(); + const CUSTOM_VIS_TITLE = 'ima custom title for a vis!'; + await dashboardPanelActions.setCustomPanelTitle(CUSTOM_VIS_TITLE); + await retry.try(async () => { + const sharedData = await PageObjects.dashboard.getPanelSharedItemData(); + const foundSharedItemTitle = !!sharedData.find(item => { + return item.title === CUSTOM_VIS_TITLE; + }); + expect(foundSharedItemTitle).to.be(true); + }); + }); + + it('data-shared-item title is cleared with an empty panel title string', async () => { + await dashboardPanelActions.setCustomPanelTitle('h\b'); + await retry.try(async () => { + const sharedData = await PageObjects.dashboard.getPanelSharedItemData(); + const foundSharedItemTitle = !!sharedData.find(item => { + return item.title === ''; + }); + expect(foundSharedItemTitle).to.be(true); + }); + }); + + it('data-shared-item title can be reset', async () => { + await dashboardPanelActions.resetCustomPanelTitle(); + await retry.try(async () => { + const sharedData = await PageObjects.dashboard.getPanelSharedItemData(); + const foundOriginalSharedItemTitle = !!sharedData.find(item => { + return item.title === originalPanelTitles[0]; + }); + expect(foundOriginalSharedItemTitle).to.be(true); + }); + }); + + it('data-shared-item title should update a saved search when using a custom panel title', async () => { + const CUSTOM_SEARCH_TITLE = 'ima custom title for a search!'; + await dashboardPanelActions.setCustomPanelTitle(CUSTOM_SEARCH_TITLE, 'Rendering Test: saved search'); + await retry.try(async () => { + const sharedData = await PageObjects.dashboard.getPanelSharedItemData(); + const foundSharedItemTitle = !!sharedData.find(item => { + return item.title === CUSTOM_SEARCH_TITLE; + }); + expect(foundSharedItemTitle).to.be(true); + }); + }); + }); +} diff --git a/test/functional/apps/dashboard/_embed_mode.js b/test/functional/apps/dashboard/_embed_mode.js new file mode 100644 index 00000000000000..922f2a9c37abe0 --- /dev/null +++ b/test/functional/apps/dashboard/_embed_mode.js @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +export default function ({ getService, getPageObjects }) { + const retry = getService('retry'); + const PageObjects = getPageObjects(['dashboard', 'common']); + const remote = getService('remote'); + + describe('embed mode', async () => { + before(async () => { + await PageObjects.dashboard.loadSavedDashboard('few panels'); + }); + + it('hides the chrome', async () => { + let isChromeVisible = await PageObjects.common.isChromeVisible(); + expect(isChromeVisible).to.be(true); + + const currentUrl = await remote.getCurrentUrl(); + const newUrl = currentUrl + '&embed=true'; + // Embed parameter only works on a hard refresh. + const useTimeStamp = true; + await remote.get(newUrl.toString(), useTimeStamp); + + await retry.try(async () => { + isChromeVisible = await PageObjects.common.isChromeVisible(); + expect(isChromeVisible).to.be(false); + }); + }); + + after(async function () { + const currentUrl = await remote.getCurrentUrl(); + const newUrl = currentUrl.replace('&embed=true', ''); + // First use the timestamp to cause a hard refresh so the new embed parameter works correctly. + let useTimeStamp = true; + await remote.get(newUrl.toString(), useTimeStamp); + // Then get rid of the timestamp so the rest of the tests work with state and app switching. + useTimeStamp = false; + await remote.get(newUrl.toString(), useTimeStamp); + }); + }); +} + diff --git a/test/functional/apps/dashboard/_embeddable_rendering.js b/test/functional/apps/dashboard/_embeddable_rendering.js new file mode 100644 index 00000000000000..da1910b065ec3e --- /dev/null +++ b/test/functional/apps/dashboard/_embeddable_rendering.js @@ -0,0 +1,136 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +/** + * This tests both that one of each visualization can be added to a dashboard (as opposed to opening an existing + * dashboard with the visualizations already on it), as well as conducts a rough type of snapshot testing by checking + * for various ui components. The downside is these tests are a bit fragile to css changes (though not as fragile as + * actual screenshot snapshot regression testing), and can be difficult to diagnose failures (which visualization + * broke?). The upside is that this offers very good coverage with a minimal time investment. + */ + +export default function ({ getService, getPageObjects }) { + const find = getService('find'); + const dashboardExpect = getService('dashboardExpect'); + const dashboardAddPanel = getService('dashboardAddPanel'); + const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize', 'discover']); + + describe('dashboard embeddable rendering', function describeIndexTests() { + before(async () => { + await PageObjects.dashboard.clickNewDashboard(); + const fromTime = '2018-01-01 00:00:00.000'; + const toTime = '2018-04-13 00:00:00.000'; + await PageObjects.header.setAbsoluteRange(fromTime, toTime); + }); + + it('adding visualizations', async () => { + await dashboardAddPanel.addEveryVisualization('"Rendering Test"'); + await PageObjects.header.waitUntilLoadingHasFinished(); + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.be(26); + }); + + it('adding saved searches', async () => { + await dashboardAddPanel.addEverySavedSearch('"Rendering Test"'); + await dashboardAddPanel.closeAddPanel(); + await PageObjects.header.waitUntilLoadingHasFinished(); + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.be(27); + + // Not neccessary but helpful for local debugging. + await PageObjects.dashboard.saveDashboard('embeddable rendering test'); + }); + + it('pie charts rendered', async () => { + await dashboardExpect.pieSliceCount(16); + }); + + it('area, bar and heatmap charts rendered', async () => { + await dashboardExpect.seriesElementCount(19); + }); + + it('data tables render', async () => { + await dashboardExpect.dataTableRowCount(5); + }); + + it('saved searches render', async () => { + await dashboardExpect.savedSearchRowCount(50); + }); + + it('goal and guage render', async () => { + await dashboardExpect.goalAndGuageLabelsExist(['63%', '56%', '11.915 GB']); + }); + + it('input controls render', async () => { + await dashboardExpect.inputControlItemCount(5); + }); + + it('metric vis renders', async () => { + await dashboardExpect.metricValuesExist(['7,544']); + }); + + it('markdown renders', async () => { + await dashboardExpect.markdownWithValuesExists(['I\'m a markdown!']); + }); + + it('line charts render', async () => { + await dashboardExpect.lineChartPointsCount(5); + }); + + it('tag cloud renders', async () => { + await dashboardExpect.tagCloudWithValuesFound(['CN', 'IN', 'US', 'BR', 'ID']); + }); + + it('timelion chart renders', async () => { + await dashboardExpect.timelionLegendCount(0); + }); + + it('tsvb guage renders', async () => { + const tsvbGuageExists = await find.existsByCssSelector('.thorHalfGauge'); + expect(tsvbGuageExists).to.be(true); + }); + + it('tsvb metric chart renders', async () => { + await dashboardExpect.tsvbMetricValuesExist(['210,007,889,606']); + }); + + it('tsvb markdown renders', async () => { + await dashboardExpect.tsvbMarkdownWithValuesExists(['Hi Avg last bytes: 6286.674715909091']); + }); + + it('tsvb table chart renders', async () => { + await dashboardExpect.tsvbTableCellCount(20); + }); + + it('tsvb time series renders', async () => { + await dashboardExpect.tsvbTimeSeriesLegendCount(1); + }); + + it('tsvb top n chart renders', async () => { + await dashboardExpect.tsvbTopNValuesExist(['5,734.79', '6,286.67']); + }); + + it('vega chart renders', async () => { + const tsvb = await find.existsByCssSelector('.vega-view-container'); + expect(tsvb).to.be(true); + }); + }); +} diff --git a/test/functional/apps/dashboard/_full_screen_mode.js b/test/functional/apps/dashboard/_full_screen_mode.js new file mode 100644 index 00000000000000..35af03ae05ac3e --- /dev/null +++ b/test/functional/apps/dashboard/_full_screen_mode.js @@ -0,0 +1,80 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +export default function ({ getService, getPageObjects }) { + const retry = getService('retry'); + const remote = getService('remote'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const PageObjects = getPageObjects(['dashboard', 'common']); + + describe('full screen mode', async () => { + before(async () => { + await PageObjects.dashboard.loadSavedDashboard('few panels'); + }); + + it('option not available in edit mode', async () => { + await PageObjects.dashboard.clickEdit(); + const exists = await PageObjects.dashboard.fullScreenModeMenuItemExists(); + expect(exists).to.be(false); + }); + + it('available in view mode', async () => { + await PageObjects.dashboard.saveDashboard('full screen test', { saveAsNew: true }); + const exists = await PageObjects.dashboard.fullScreenModeMenuItemExists(); + expect(exists).to.be(true); + }); + + it('hides the chrome', async () => { + let isChromeVisible = await PageObjects.common.isChromeVisible(); + expect(isChromeVisible).to.be(true); + + await PageObjects.dashboard.clickFullScreenMode(); + + await retry.try(async () => { + isChromeVisible = await PageObjects.common.isChromeVisible(); + expect(isChromeVisible).to.be(false); + }); + }); + + it('displays exit full screen logo button', async () => { + const exists = await PageObjects.dashboard.exitFullScreenLogoButtonExists(); + expect(exists).to.be(true); + }); + + it('displays exit full screen logo button when panel is expanded', async () => { + await dashboardPanelActions.toggleExpandPanel(); + + const exists = await PageObjects.dashboard.exitFullScreenTextButtonExists(); + expect(exists).to.be(true); + }); + + it('exits when the text button is clicked on', async () => { + const logoButton = await PageObjects.dashboard.getExitFullScreenLogoButton(); + await remote.moveMouseTo(logoButton); + await PageObjects.dashboard.clickExitFullScreenTextButton(); + + await retry.try(async () => { + const isChromeVisible = await PageObjects.common.isChromeVisible(); + expect(isChromeVisible).to.be(true); + }); + }); + }); +} diff --git a/test/functional/apps/dashboard/_panel_controls.js b/test/functional/apps/dashboard/_panel_controls.js index d0986c3d8d0fc7..158efae00e0ccf 100644 --- a/test/functional/apps/dashboard/_panel_controls.js +++ b/test/functional/apps/dashboard/_panel_controls.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; @@ -6,9 +25,10 @@ import { } from '../../../../src/core_plugins/kibana/public/visualize/visualize_constants'; export default function ({ getService, getPageObjects }) { - const testSubjects = getService('testSubjects'); const kibanaServer = getService('kibanaServer'); const remote = getService('remote'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const dashboardAddPanel = getService('dashboardAddPanel'); const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'discover']); const dashboardName = 'Dashboard Panel Controls Test'; @@ -33,24 +53,30 @@ export default function ({ getService, getPageObjects }) { describe('panel edit controls', function () { before(async () => { await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.setTimepickerInDataRange(); - await PageObjects.dashboard.addVisualization(PIE_CHART_VIS_NAME); + await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); }); it('are hidden in view mode', async function () { await PageObjects.dashboard.saveDashboard(dashboardName); - const panelToggleMenu = await testSubjects.exists('dashboardPanelToggleMenuIcon'); - expect(panelToggleMenu).to.equal(false); + + await dashboardPanelActions.openContextMenu(); + const editLinkExists = await dashboardPanelActions.editPanelActionExists(); + const removeExists = await dashboardPanelActions.removePanelActionExists(); + + expect(editLinkExists).to.equal(false); + expect(removeExists).to.equal(false); }); it('are shown in edit mode', async function () { await PageObjects.dashboard.clickEdit(); - const panelToggleMenu = await testSubjects.exists('dashboardPanelToggleMenuIcon'); - expect(panelToggleMenu).to.equal(true); - await testSubjects.click('dashboardPanelToggleMenuIcon'); - const editLinkExists = await testSubjects.exists('dashboardPanelEditLink'); - const removeExists = await testSubjects.exists('dashboardPanelRemoveIcon'); + const isContextMenuIconVisible = await dashboardPanelActions.isContextMenuIconVisible(); + expect(isContextMenuIconVisible).to.equal(true); + await dashboardPanelActions.openContextMenu(); + + const editLinkExists = await dashboardPanelActions.editPanelActionExists(); + const removeExists = await dashboardPanelActions.removePanelActionExists(); expect(editLinkExists).to.equal(true); expect(removeExists).to.equal(true); @@ -64,11 +90,11 @@ export default function ({ getService, getPageObjects }) { await remote.get(currentUrl.toString(), true); await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.dashboard.showPanelEditControlsDropdownMenu(); - const editLinkExists = await testSubjects.exists('dashboardPanelEditLink'); + await dashboardPanelActions.openContextMenu(); + const editLinkExists = await dashboardPanelActions.editPanelActionExists(); expect(editLinkExists).to.equal(true); - const removeExists = await testSubjects.exists('dashboardPanelRemoveIcon'); + const removeExists = await dashboardPanelActions.removePanelActionExists(); expect(removeExists).to.equal(true); // Get rid of the timestamp in the url. @@ -78,32 +104,33 @@ export default function ({ getService, getPageObjects }) { describe('on an expanded panel', function () { it('are hidden in view mode', async function () { await PageObjects.dashboard.saveDashboard(dashboardName); - await PageObjects.dashboard.toggleExpandPanel(); + await dashboardPanelActions.toggleExpandPanel(); - const panelToggleMenu = await testSubjects.exists('dashboardPanelToggleMenuIcon'); - expect(panelToggleMenu).to.equal(false); + await dashboardPanelActions.openContextMenu(); + const editLinkExists = await dashboardPanelActions.editPanelActionExists(); + const removeExists = await dashboardPanelActions.removePanelActionExists(); + + expect(editLinkExists).to.equal(false); + expect(removeExists).to.equal(false); }); it('in edit mode hides remove icons ', async function () { await PageObjects.dashboard.clickEdit(); - - const panelToggleMenu = await testSubjects.exists('dashboardPanelToggleMenuIcon'); - expect(panelToggleMenu).to.equal(true); - await testSubjects.click('dashboardPanelToggleMenuIcon'); - const editLinkExists = await testSubjects.exists('dashboardPanelEditLink'); - const removeExists = await testSubjects.exists('dashboardPanelRemoveIcon'); + await dashboardPanelActions.openContextMenu(); + const editLinkExists = await dashboardPanelActions.editPanelActionExists(); + const removeExists = await dashboardPanelActions.removePanelActionExists(); expect(editLinkExists).to.equal(true); expect(removeExists).to.equal(false); - await PageObjects.dashboard.toggleExpandPanel(); + await dashboardPanelActions.toggleExpandPanel(); }); }); describe('visualization object edit menu', () => { it('opens a visualization when edit link is clicked', async () => { - await testSubjects.click('dashboardPanelToggleMenuIcon'); - await PageObjects.dashboard.clickDashboardPanelEditLink(); + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickEdit(); await PageObjects.header.waitUntilLoadingHasFinished(); const currentUrl = await remote.getCurrentUrl(); expect(currentUrl).to.contain(VisualizeConstants.EDIT_PATH); @@ -112,7 +139,7 @@ export default function ({ getService, getPageObjects }) { it('deletes the visualization when delete link is clicked', async () => { await PageObjects.header.clickDashboard(); await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.dashboard.clickDashboardPanelRemoveIcon(); + await dashboardPanelActions.removePanel(); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be(0); @@ -126,14 +153,14 @@ export default function ({ getService, getPageObjects }) { await PageObjects.discover.saveSearch('my search'); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.header.clickDashboard(); - await PageObjects.dashboard.addSavedSearch('my search'); + await dashboardAddPanel.addSavedSearch('my search'); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be(1); }); it('opens a saved search when edit link is clicked', async () => { - await PageObjects.dashboard.clickDashboardPanelEditLink(); + await dashboardPanelActions.clickEdit(); await PageObjects.header.waitUntilLoadingHasFinished(); const queryName = await PageObjects.discover.getCurrentQueryName(); expect(queryName).to.be('my search'); @@ -142,7 +169,7 @@ export default function ({ getService, getPageObjects }) { it('deletes the saved search when delete link is clicked', async () => { await PageObjects.header.clickDashboard(); await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.dashboard.clickDashboardPanelRemoveIcon(); + await dashboardPanelActions.removePanel(); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be(0); @@ -154,8 +181,8 @@ export default function ({ getService, getPageObjects }) { describe('panel expand control', function () { it('shown in edit mode', async function () { await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); - await testSubjects.click('dashboardPanelToggleMenuIcon'); - const expandExists = await testSubjects.exists('dashboardPanelExpandIcon'); + await dashboardPanelActions.openContextMenu(); + const expandExists = await dashboardPanelActions.toggleExpandActionExists(); expect(expandExists).to.equal(true); }); }); diff --git a/test/functional/apps/dashboard/_panel_expand_toggle.js b/test/functional/apps/dashboard/_panel_expand_toggle.js new file mode 100644 index 00000000000000..ec9ebb2f002851 --- /dev/null +++ b/test/functional/apps/dashboard/_panel_expand_toggle.js @@ -0,0 +1,88 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +export default function ({ getService, getPageObjects }) { + const retry = getService('retry'); + const remote = getService('remote'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const PageObjects = getPageObjects(['dashboard', 'visualize', 'header']); + + describe('expanding a panel', () => { + before(async () => { + await PageObjects.dashboard.loadSavedDashboard('few panels'); + }); + + it('hides other panels', async () => { + await dashboardPanelActions.toggleExpandPanel(); + await retry.try(async () => { + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.eql(1); + }); + }); + + it('does not show the spy pane toggle if mouse is not hovering', async () => { + // move mouse off the panel. + await PageObjects.header.clickTimepicker(); + + // no spy pane without hover + const spyToggleExists = await PageObjects.visualize.getSpyToggleExists(); + expect(spyToggleExists).to.be(false); + }); + + it('shows the spy pane toggle on hover', async () => { + const panels = await PageObjects.dashboard.getDashboardPanels(); + // Simulate hover + await remote.moveMouseTo(panels[0]); + const spyToggleExists = await PageObjects.visualize.getSpyToggleExists(); + expect(spyToggleExists).to.be(true); + }); + + // This was an actual bug that appeared, where the spy pane appeared on panels after adding them, but + // disappeared when a new dashboard was opened up. + it('shows the spy pane toggle directly after opening a dashboard', async () => { + await PageObjects.dashboard.clickEdit(); + await PageObjects.dashboard.saveDashboard('spy pane test', { saveAsNew: true }); + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.loadSavedDashboard('spy pane test'); + const panels = await PageObjects.dashboard.getDashboardPanels(); + // Simulate hover + await remote.moveMouseTo(panels[1]); + const spyToggleExists = await PageObjects.visualize.getSpyToggleExists(); + expect(spyToggleExists).to.be(true); + }); + + it('shows other panels after being minimized', async () => { + const panelCount = await PageObjects.dashboard.getPanelCount(); + // Panels are all minimized on a fresh open of a dashboard, so we need to re-expand in order to then minimize. + await dashboardPanelActions.toggleExpandPanel(); + await dashboardPanelActions.toggleExpandPanel(); + + + // Add a retry to fix https://github.com/elastic/kibana/issues/14574. Perhaps the recent changes to this + // being a CSS update is causing the UI to change slower than grabbing the panels? + retry.try(async () => { + const panelCountAfterMaxThenMinimize = await PageObjects.dashboard.getPanelCount(); + expect(panelCountAfterMaxThenMinimize).to.be(panelCount); + }); + }); + }); + +} diff --git a/test/functional/apps/dashboard/_time_zones.js b/test/functional/apps/dashboard/_time_zones.js new file mode 100644 index 00000000000000..0546634927ad39 --- /dev/null +++ b/test/functional/apps/dashboard/_time_zones.js @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import path from 'path'; +import expect from 'expect.js'; + +export default function ({ getService, getPageObjects }) { + const dashboardExpect = getService('dashboardExpect'); + const PageObjects = getPageObjects(['dashboard', 'header', 'settings', 'common']); + + describe('dashboard time zones', () => { + before(async () => { + await PageObjects.settings.navigateTo(); + await PageObjects.settings.clickKibanaSavedObjects(); + await PageObjects.settings.importFile(path.join(__dirname, 'exports', 'timezonetest_6_2_4.json')); + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.loadSavedDashboard('time zone test'); + }); + + after(async () => { + await PageObjects.settings.navigateTo(); + await PageObjects.settings.clickKibanaSettings(); + await PageObjects.settings.setAdvancedSettingsSelect('dateFormat:tz', 'UTC'); + await PageObjects.common.navigateToApp('dashboard'); + }); + + it('Exported dashboard adjusts EST time to UTC', async () => { + const timeRange = await PageObjects.header.getPrettyDuration(); + expect(timeRange).to.be('April 10th 2018, 03:00:00.000 to April 10th 2018, 04:00:00.000'); + await dashboardExpect.pieSliceCount(4); + }); + + it('Changing timezone changes dashboard timestamp and shows the same data', async () => { + await PageObjects.settings.navigateTo(); + await PageObjects.settings.clickKibanaSettings(); + await PageObjects.settings.setAdvancedSettingsSelect('dateFormat:tz', 'EST'); + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.loadSavedDashboard('time zone test'); + const timeRange = await PageObjects.header.getPrettyDuration(); + expect(timeRange).to.be('April 9th 2018, 22:00:00.000 to April 9th 2018, 23:00:00.000'); + await dashboardExpect.pieSliceCount(4); + }); + }); +} diff --git a/test/functional/apps/dashboard/_view_edit.js b/test/functional/apps/dashboard/_view_edit.js index 1cd910f89bfaf9..f6fbd9ca93265b 100644 --- a/test/functional/apps/dashboard/_view_edit.js +++ b/test/functional/apps/dashboard/_view_edit.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -5,6 +24,8 @@ export default function ({ getService, getPageObjects }) { const kibanaServer = getService('kibanaServer'); const retry = getService('retry'); const remote = getService('remote'); + const queryBar = getService('queryBar'); + const dashboardAddPanel = getService('dashboardAddPanel'); const PageObjects = getPageObjects(['dashboard', 'header', 'common', 'visualize']); const dashboardName = 'Dashboard View Edit Test'; @@ -28,7 +49,7 @@ export default function ({ getService, getPageObjects }) { it('create test dashboard', async function () { await PageObjects.dashboard.gotoDashboardLandingPage(); await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.dashboard.addVisualizations(PageObjects.dashboard.getTestVisualizationNames()); + await dashboardAddPanel.addVisualizations(PageObjects.dashboard.getTestVisualizationNames()); const isDashboardSaved = await PageObjects.dashboard.saveDashboard(dashboardName); expect(isDashboardSaved).to.eql(true); }); @@ -78,21 +99,21 @@ export default function ({ getService, getPageObjects }) { }); it('when the query is edited and applied', async function () { - const originalQuery = await PageObjects.dashboard.getQuery(); - await PageObjects.dashboard.setQuery(`${originalQuery} and extra stuff`); - await PageObjects.dashboard.clickFilterButton(); + const originalQuery = await queryBar.getQueryString(); + await queryBar.setQuery(`${originalQuery} and extra stuff`); + await queryBar.submitQuery(); await PageObjects.dashboard.clickCancelOutOfEditMode(); // confirm lose changes await PageObjects.common.clickConfirmOnModal(); - const query = await PageObjects.dashboard.getQuery(); + const query = await queryBar.getQueryString(); expect(query).to.equal(originalQuery); }); it('when a filter is deleted', async function () { - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); await PageObjects.dashboard.filterOnPieSlice(); await PageObjects.dashboard.saveDashboard(dashboardName); @@ -125,8 +146,8 @@ export default function ({ getService, getPageObjects }) { }); it('when a new vis is added', async function () { - await PageObjects.dashboard.clickAddVisualization(); - await PageObjects.dashboard.clickAddNewVisualizationLink(); + await dashboardAddPanel.ensureAddPanelIsShowing(); + await dashboardAddPanel.clickAddNewEmbeddableLink(); await PageObjects.visualize.clickAreaChart(); await PageObjects.visualize.clickNewSearch(); await PageObjects.visualize.saveVisualization('new viz panel'); @@ -142,7 +163,7 @@ export default function ({ getService, getPageObjects }) { }); it('when an existing vis is added', async function () { - await PageObjects.dashboard.addVisualization('new viz panel'); + await dashboardAddPanel.addVisualization('new viz panel'); await PageObjects.dashboard.clickCancelOutOfEditMode(); // confirm lose changes @@ -217,7 +238,7 @@ export default function ({ getService, getPageObjects }) { it('when a dashboard has a filter and remains unchanged', async function () { await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); await PageObjects.dashboard.filterOnPieSlice(); await PageObjects.dashboard.saveDashboard(dashboardName); await PageObjects.dashboard.clickEdit(); @@ -231,8 +252,8 @@ export default function ({ getService, getPageObjects }) { it('when the query is edited but not applied', async function () { await PageObjects.dashboard.gotoDashboardEditMode(dashboardName); - const originalQuery = await PageObjects.dashboard.getQuery(); - await PageObjects.dashboard.setQuery(`${originalQuery} extra stuff`); + const originalQuery = await queryBar.getQueryString(); + await queryBar.setQuery(`${originalQuery} extra stuff`); await PageObjects.dashboard.clickCancelOutOfEditMode(); @@ -240,7 +261,7 @@ export default function ({ getService, getPageObjects }) { expect(isOpen).to.be(false); await PageObjects.dashboard.loadSavedDashboard(dashboardName); - const query = await PageObjects.dashboard.getQuery(); + const query = await queryBar.getQueryString(); expect(query).to.equal(originalQuery); }); }); diff --git a/test/functional/apps/dashboard/exports/timezonetest_6_2_4.json b/test/functional/apps/dashboard/exports/timezonetest_6_2_4.json new file mode 100644 index 00000000000000..c18b460aae6323 --- /dev/null +++ b/test/functional/apps/dashboard/exports/timezonetest_6_2_4.json @@ -0,0 +1,25 @@ +[ + { + "_id": "61d06bc0-5215-11e8-82a7-0b6f5e824cae", + "_type": "dashboard", + "_source": { + "title": "time zone test", + "hits": 0, + "description": "", + "panelsJSON": "[{\"gridData\":{\"h\":3,\"i\":\"1\",\"w\":6,\"x\":0,\"y\":0},\"id\":\"3fe22200-3dcb-11e8-8660-4d65aa086b3c\",\"panelIndex\":\"1\",\"type\":\"visualization\",\"version\":\"6.2.4\"}]", + "optionsJSON": "{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}", + "version": 1, + "timeRestore": true, + "timeTo": "Tue Apr 09 2018 23:00:00 GMT-0500", + "timeFrom": "Mon Apr 09 2018 22:00:00 GMT-0500", + "refreshInterval": { + "display": "Off", + "pause": false, + "value": 0 + }, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" + } + } + } +] diff --git a/test/functional/apps/dashboard/index.js b/test/functional/apps/dashboard/index.js index 52f41245fb0fc9..554757ba0e1724 100644 --- a/test/functional/apps/dashboard/index.js +++ b/test/functional/apps/dashboard/index.js @@ -1,22 +1,76 @@ -export default function ({ getService, loadTestFile }) { +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export default function ({ getService, loadTestFile, getPageObjects }) { const remote = getService('remote'); + const esArchiver = getService('esArchiver'); + const PageObjects = getPageObjects(['dashboard']); describe('dashboard app', function () { - before(() => remote.setWindowSize(1200, 900)); - loadTestFile(require.resolve('./_dashboard_filter_bar')); - loadTestFile(require.resolve('./_dashboard_time_picker')); - loadTestFile(require.resolve('./_dashboard_shared_attributes')); - loadTestFile(require.resolve('./_bwc_shared_urls')); - loadTestFile(require.resolve('./_dashboard_queries')); - loadTestFile(require.resolve('./_dashboard_snapshots')); - loadTestFile(require.resolve('./_dashboard_grid')); - loadTestFile(require.resolve('./_panel_controls')); - loadTestFile(require.resolve('./_view_edit')); - loadTestFile(require.resolve('./_dashboard')); - loadTestFile(require.resolve('./_dashboard_state')); - loadTestFile(require.resolve('./_dashboard_save')); - loadTestFile(require.resolve('./_dashboard_time')); - loadTestFile(require.resolve('./_dashboard_listing')); - loadTestFile(require.resolve('./_dashboard_clone')); + describe('using current data', function () { + before(async () => { + await remote.setWindowSize(1300, 900); + await PageObjects.dashboard.initTests({ + kibanaIndex: 'dashboard/current/kibana', + dataIndex: 'dashboard/current/data', + defaultIndex: 'logstash-*', + }); + await PageObjects.dashboard.preserveCrossAppState(); + }); + + after(async function () { + await PageObjects.dashboard.clearSavedObjectsFromAppLinks(); + await esArchiver.unload('dashboard/current/kibana'); + await esArchiver.unload('dashboard/current/data'); + }); + + // This has to be first since the other tests create some embeddables as side affects and our counting assumes + // a fresh index. + loadTestFile(require.resolve('./_embeddable_rendering')); + loadTestFile(require.resolve('./_create_and_add_embeddables')); + loadTestFile(require.resolve('./_time_zones')); + loadTestFile(require.resolve('./_dashboard_options')); + loadTestFile(require.resolve('./_data_shared_attributes')); + loadTestFile(require.resolve('./_embed_mode')); + loadTestFile(require.resolve('./_full_screen_mode')); + loadTestFile(require.resolve('./_dashboard_filter_bar')); + loadTestFile(require.resolve('./_dashboard_filtering')); + loadTestFile(require.resolve('./_panel_expand_toggle')); + loadTestFile(require.resolve('./_dashboard_grid')); + loadTestFile(require.resolve('./_dashboard_snapshots')); + }); + + // Each of these tests call initTests themselves, the way it was originally written. The above tests only load + // the data once to save on time. Eventually, all of these tests should just use current data and we can reserve + // legacy data only for specifically testing BWC situations. + describe('using legacy data', function () { + before(() => remote.setWindowSize(1200, 900)); + + loadTestFile(require.resolve('./_dashboard_time_picker')); + loadTestFile(require.resolve('./_bwc_shared_urls')); + loadTestFile(require.resolve('./_panel_controls')); + loadTestFile(require.resolve('./_view_edit')); + loadTestFile(require.resolve('./_dashboard_state')); + loadTestFile(require.resolve('./_dashboard_save')); + loadTestFile(require.resolve('./_dashboard_time')); + loadTestFile(require.resolve('./_dashboard_listing')); + loadTestFile(require.resolve('./_dashboard_clone')); + }); }); } diff --git a/test/functional/apps/dashboard/set_up_tests.js b/test/functional/apps/dashboard/set_up_tests.js deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/test/functional/apps/discover/_collapse_expand.js b/test/functional/apps/discover/_collapse_expand.js index 2a350e857da304..6bdfdf92140c0a 100644 --- a/test/functional/apps/discover/_collapse_expand.js +++ b/test/functional/apps/discover/_collapse_expand.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js index 08ba59416c414d..c72b2376c419c7 100644 --- a/test/functional/apps/discover/_discover.js +++ b/test/functional/apps/discover/_discover.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/discover/_errors.js b/test/functional/apps/discover/_errors.js index 50a437cc2b1cba..20daa6d0f7dade 100644 --- a/test/functional/apps/discover/_errors.js +++ b/test/functional/apps/discover/_errors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/discover/_field_data.js b/test/functional/apps/discover/_field_data.js index 7a507c1f25cb1c..1e55b8f12c0344 100644 --- a/test/functional/apps/discover/_field_data.js +++ b/test/functional/apps/discover/_field_data.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/discover/_large_string.js b/test/functional/apps/discover/_large_string.js index ec719e90b92a9f..cc248b353d633c 100644 --- a/test/functional/apps/discover/_large_string.js +++ b/test/functional/apps/discover/_large_string.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/discover/_shared_links.js b/test/functional/apps/discover/_shared_links.js index d63edcc5544b6f..24d5b46bf7bf8a 100644 --- a/test/functional/apps/discover/_shared_links.js +++ b/test/functional/apps/discover/_shared_links.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/discover/_source_filters.js b/test/functional/apps/discover/_source_filters.js index b99af2773b97dd..5374d8c30eede9 100644 --- a/test/functional/apps/discover/_source_filters.js +++ b/test/functional/apps/discover/_source_filters.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/discover/index.js b/test/functional/apps/discover/index.js index ca47049784dfb1..e17db88d6a463e 100644 --- a/test/functional/apps/discover/index.js +++ b/test/functional/apps/discover/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, loadTestFile }) { const esArchiver = getService('esArchiver'); const remote = getService('remote'); diff --git a/test/functional/apps/getting_started/_shakespeare.js b/test/functional/apps/getting_started/_shakespeare.js index 09011413882dd9..1ca495624b3c5b 100644 --- a/test/functional/apps/getting_started/_shakespeare.js +++ b/test/functional/apps/getting_started/_shakespeare.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/getting_started/index.js b/test/functional/apps/getting_started/index.js index 55a4e05f79c80b..2683372b9df16c 100644 --- a/test/functional/apps/getting_started/index.js +++ b/test/functional/apps/getting_started/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, loadTestFile }) { const remote = getService('remote'); diff --git a/test/functional/apps/home/_add_data.js b/test/functional/apps/home/_add_data.js index 40e7ce5f290d93..0902bd8d2161ce 100644 --- a/test/functional/apps/home/_add_data.js +++ b/test/functional/apps/home/_add_data.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/home/_home.js b/test/functional/apps/home/_home.js index a68784b9489e3c..9b7914f31ba8f3 100644 --- a/test/functional/apps/home/_home.js +++ b/test/functional/apps/home/_home.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; diff --git a/test/functional/apps/home/_sample_data.js b/test/functional/apps/home/_sample_data.js new file mode 100644 index 00000000000000..48cc3cf5099360 --- /dev/null +++ b/test/functional/apps/home/_sample_data.js @@ -0,0 +1,111 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from 'expect.js'; + +export default function ({ getService, getPageObjects }) { + const retry = getService('retry'); + const find = getService('find'); + const dashboardExpect = getService('dashboardExpect'); + const PageObjects = getPageObjects(['common', 'header', 'home', 'dashboard']); + + describe('sample data', function describeIndexTests() { + + before(async () => { + await PageObjects.common.navigateToUrl('home', 'tutorial_directory/sampleData'); + await PageObjects.header.waitUntilLoadingHasFinished(); + }); + + it('should display registered sample data sets', async ()=> { + await retry.try(async () => { + const exists = await PageObjects.home.doesSampleDataSetExist('flights'); + expect(exists).to.be(true); + }); + }); + + it('should install sample data set', async ()=> { + await PageObjects.home.addSampleDataSet('flights'); + await retry.try(async () => { + const successToastExists = await PageObjects.home.doesSampleDataSetSuccessfulInstallToastExist(); + expect(successToastExists).to.be(true); + }); + + const isInstalled = await PageObjects.home.isSampleDataSetInstalled('flights'); + expect(isInstalled).to.be(true); + }); + + describe('dashboard', () => { + after(async () => { + await PageObjects.common.navigateToUrl('home', 'tutorial_directory/sampleData'); + await PageObjects.header.waitUntilLoadingHasFinished(); + }); + + it('should launch sample data set dashboard', async ()=> { + await PageObjects.home.launchSampleDataSet('flights'); + await PageObjects.header.waitUntilLoadingHasFinished(); + const today = new Date(); + const todayYearMonthDay = today.toISOString().substring(0, 10); + const fromTime = `${todayYearMonthDay} 00:00:00.000`; + const toTime = `${todayYearMonthDay} 23:59:59.999`; + await PageObjects.header.setAbsoluteRange(fromTime, toTime); + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.be(19); + }); + + it.skip('pie charts rendered', async () => { + await dashboardExpect.pieSliceCount(4); + }); + + it.skip('area, bar and heatmap charts rendered', async () => { + await dashboardExpect.seriesElementCount(15); + }); + + it.skip('saved searches render', async () => { + await dashboardExpect.savedSearchRowCount(50); + }); + + it.skip('input controls render', async () => { + await dashboardExpect.inputControlItemCount(3); + }); + + it.skip('tag cloud renders', async () => { + await dashboardExpect.tagCloudWithValuesFound(['Sunny', 'Rain', 'Clear', 'Cloudy', 'Hail']); + }); + + it.skip('vega chart renders', async () => { + const tsvb = await find.existsByCssSelector('.vega-view-container'); + expect(tsvb).to.be(true); + }); + }); + + // needs to be in describe block so it is run after 'dashboard describe block' + describe('uninstall', () => { + it('should uninstall sample data set', async ()=> { + await PageObjects.home.removeSampleDataSet('flights'); + await retry.try(async () => { + const successToastExists = await PageObjects.home.doesSampleDataSetSuccessfulUninstallToastExist(); + expect(successToastExists).to.be(true); + }); + + const isInstalled = await PageObjects.home.isSampleDataSetInstalled('flights'); + expect(isInstalled).to.be(false); + }); + }); + }); +} diff --git a/test/functional/apps/home/index.js b/test/functional/apps/home/index.js index bae4b963d9a2c3..b4ac690c37e0ab 100644 --- a/test/functional/apps/home/index.js +++ b/test/functional/apps/home/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, loadTestFile }) { const remote = getService('remote'); @@ -8,5 +27,6 @@ export default function ({ getService, loadTestFile }) { loadTestFile(require.resolve('./_home')); loadTestFile(require.resolve('./_add_data')); + loadTestFile(require.resolve('./_sample_data')); }); } diff --git a/test/functional/apps/management/_create_index_pattern_wizard.js b/test/functional/apps/management/_create_index_pattern_wizard.js index 6a90116b543b41..ca84f192f7daeb 100644 --- a/test/functional/apps/management/_create_index_pattern_wizard.js +++ b/test/functional/apps/management/_create_index_pattern_wizard.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/management/_handle_alias.js b/test/functional/apps/management/_handle_alias.js index 8a3613ec1bdf79..8dbee1a74fef06 100644 --- a/test/functional/apps/management/_handle_alias.js +++ b/test/functional/apps/management/_handle_alias.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/management/_import_objects.js b/test/functional/apps/management/_import_objects.js index 9cb5cc6d0f52b1..c1742b701c0d92 100644 --- a/test/functional/apps/management/_import_objects.js +++ b/test/functional/apps/management/_import_objects.js @@ -1,8 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + 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', 'header']); @@ -22,79 +40,78 @@ export default function ({ getService, getPageObjects }) { it('should import saved objects normally', async function () { await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects.json')); - await PageObjects.common.clickConfirmOnModal(); await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.settings.clickVisualizationsTab(); - const rowCount = await retry.try(async () => { - const rows = await PageObjects.settings.getVisualizationRows(); - return rows.length; - }); - expect(rowCount).to.be(2); + await PageObjects.settings.clickImportDone(); + await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); + const objects = await PageObjects.settings.getSavedObjectsInTable(); + expect(objects.length).to.be(3); }); it('should import conflicts using a confirm modal', async function () { await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects-conflicts.json')); - await PageObjects.common.clickConfirmOnModal(); + await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.settings.setImportIndexFieldOption(2); - await PageObjects.settings.clickChangeIndexConfirmButton(); + await PageObjects.settings.clickConfirmConflicts(); await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.settings.clickVisualizationsTab(); - const rowCount = await retry.try(async () => { - const rows = await PageObjects.settings.getVisualizationRows(); - return rows.length; - }); - expect(rowCount).to.be(2); + await PageObjects.settings.clickImportDone(); + await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); + const objects = await PageObjects.settings.getSavedObjectsInTable(); + expect(objects.length).to.be(3); }); it('should allow for overrides', async function () { await PageObjects.settings.clickKibanaSavedObjects(); // Put in data which already exists - await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_exists.json')); - // Say we want to be asked - await PageObjects.common.clickCancelOnModal(); + await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_exists.json'), false); + // Wait for all the saves to happen + await PageObjects.header.waitUntilLoadingHasFinished(); // Interact with the conflict modal await PageObjects.settings.setImportIndexFieldOption(2); - await PageObjects.settings.clickChangeIndexConfirmButton(); + await PageObjects.settings.clickConfirmConflicts(); // Now confirm we want to override await PageObjects.common.clickConfirmOnModal(); + // Wait for all the saves to happen await PageObjects.header.waitUntilLoadingHasFinished(); + // Finish the flyout + await PageObjects.settings.clickImportDone(); + // Wait... + await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); - await PageObjects.settings.clickVisualizationsTab(); - const rowCount = await retry.try(async () => { - const rows = await PageObjects.settings.getVisualizationRows(); - return rows.length; - }); - expect(rowCount).to.be(1); + const objects = await PageObjects.settings.getSavedObjectsInTable(); + expect(objects.length).to.be(2); }); it('should allow for cancelling overrides', async function () { await PageObjects.settings.clickKibanaSavedObjects(); // Put in data which already exists - await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_exists.json')); - // Say we want to be asked - await PageObjects.common.clickCancelOnModal(); + await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_exists.json'), false); + // Wait for all the saves to happen + await PageObjects.header.waitUntilLoadingHasFinished(); // Interact with the conflict modal await PageObjects.settings.setImportIndexFieldOption(2); - await PageObjects.settings.clickChangeIndexConfirmButton(); + await PageObjects.settings.clickConfirmConflicts(); // Now cancel the override await PageObjects.common.clickCancelOnModal(); + // Wait for all saves to happen + await PageObjects.header.waitUntilLoadingHasFinished(); + // Finish the flyout + await PageObjects.settings.clickImportDone(); + // Wait for table to refresh + await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); - await PageObjects.settings.clickVisualizationsTab(); - const rowCount = await retry.try(async () => { - const rows = await PageObjects.settings.getVisualizationRows(); - return rows.length; - }); - expect(rowCount).to.be(1); + const objects = await PageObjects.settings.getSavedObjectsInTable(); + expect(objects.length).to.be(2); }); it('should handle saved searches and objects with saved searches properly', async function () { // First, import the saved search await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_saved_search.json')); - await PageObjects.common.clickConfirmOnModal(); + // Wait for all the saves to happen + await PageObjects.header.waitUntilLoadingHasFinished(); // Second, we need to delete the index pattern await PageObjects.settings.navigateTo(); @@ -103,26 +120,52 @@ export default function ({ getService, getPageObjects }) { await PageObjects.settings.removeIndexPattern(); // Last, import a saved object connected to the saved search - // This should NOT show the modal + // This should NOT show the conflicts await PageObjects.settings.navigateTo(); await PageObjects.settings.clickKibanaSavedObjects(); await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_connected_to_saved_search.json')); - await PageObjects.common.clickConfirmOnModal(); + // Wait for all the saves to happen + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.settings.clickImportDone(); + await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); + + const objects = await PageObjects.settings.getSavedObjectsInTable(); + expect(objects.length).to.be(2); + }); + + it('should work with index patterns', async () => { + // First, import the objects + await PageObjects.settings.clickKibanaSavedObjects(); + await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_with_index_patterns.json')); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.settings.clickImportDone(); + // Wait for all the saves to happen + await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); + + const objects = await PageObjects.settings.getSavedObjectsInTable(); + expect(objects.length).to.be(2); + }); + + it('should work when the index pattern does not exist', async () => { + // First, we need to delete the index pattern + await PageObjects.settings.navigateTo(); + await PageObjects.settings.clickKibanaIndices(); + await PageObjects.settings.clickOnOnlyIndexPattern(); + await PageObjects.settings.removeIndexPattern(); + + // Second, create it + await PageObjects.settings.createIndexPattern('logstash-', '@timestamp'); + + // Then, import the objects + await PageObjects.settings.clickKibanaSavedObjects(); + await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects_with_index_patterns.json')); await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.settings.clickImportDone(); + // Wait for all the saves to happen + await PageObjects.settings.waitUntilSavedObjectsTableIsNotLoading(); - await PageObjects.settings.clickVisualizationsTab(); - const vizRowCount = await retry.try(async () => { - const rows = await PageObjects.settings.getVisualizationRows(); - return rows.length; - }); - expect(vizRowCount).to.be(1); - - await PageObjects.settings.clickSearchesTab(); - const searchRowCount = await retry.try(async () => { - const rows = await PageObjects.settings.getVisualizationRows(); - return rows.length; - }); - expect(searchRowCount).to.be(1); + const objects = await PageObjects.settings.getSavedObjectsInTable(); + expect(objects.length).to.be(2); }); }); } diff --git a/test/functional/apps/management/_index_pattern_create_delete.js b/test/functional/apps/management/_index_pattern_create_delete.js index 76a4ab9f64d7a2..df5a4ea1d74743 100644 --- a/test/functional/apps/management/_index_pattern_create_delete.js +++ b/test/functional/apps/management/_index_pattern_create_delete.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/management/_index_pattern_filter.js b/test/functional/apps/management/_index_pattern_filter.js index 71fa7a59db0b53..0e4812a267c28e 100644 --- a/test/functional/apps/management/_index_pattern_filter.js +++ b/test/functional/apps/management/_index_pattern_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/management/_index_pattern_popularity.js b/test/functional/apps/management/_index_pattern_popularity.js index 48d6fee60dda3c..4a1039fb081544 100644 --- a/test/functional/apps/management/_index_pattern_popularity.js +++ b/test/functional/apps/management/_index_pattern_popularity.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -25,17 +44,8 @@ export default function ({ getService, getPageObjects }) { describe('change popularity', function indexPatternCreation() { const fieldName = 'geo.coordinates'; - // set the page size to All again, https://github.com/elastic/kibana/issues/5030 - // TODO: remove this after issue #5030 is closed - async function fix5030() { - await PageObjects.settings.setPageSize(50); - await PageObjects.common.sleep(1000); - } - beforeEach(async function () { // increase Popularity of geo.coordinates - await PageObjects.settings.setPageSize(50); - await PageObjects.common.sleep(1000); log.debug('Starting openControlsByName (' + fieldName + ')'); await PageObjects.settings.openControlsByName(fieldName); log.debug('increasePopularity'); @@ -56,7 +66,6 @@ export default function ({ getService, getPageObjects }) { it('should be reset on cancel', async function () { // Cancel saving the popularity change await PageObjects.settings.controlChangeCancel(); - await fix5030(); await PageObjects.settings.openControlsByName(fieldName); // check that it is 0 (previous increase was cancelled const popularity = await PageObjects.settings.getPopularity(); @@ -67,7 +76,6 @@ export default function ({ getService, getPageObjects }) { it('can be saved', async function () { // Saving the popularity change await PageObjects.settings.controlChangeSave(); - await fix5030(); await PageObjects.settings.openControlsByName(fieldName); const popularity = await PageObjects.settings.getPopularity(); log.debug('popularity = ' + popularity); diff --git a/test/functional/apps/management/_index_pattern_results_sort.js b/test/functional/apps/management/_index_pattern_results_sort.js index 50d37088404698..d2406ae240bf2d 100644 --- a/test/functional/apps/management/_index_pattern_results_sort.js +++ b/test/functional/apps/management/_index_pattern_results_sort.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -70,10 +89,7 @@ export default function ({ getService, getPageObjects }) { }); describe('field list pagination', function () { - const EXPECTED_DEFAULT_PAGE_SIZE = 10; const EXPECTED_FIELD_COUNT = 86; - const EXPECTED_LAST_PAGE_COUNT = EXPECTED_FIELD_COUNT % EXPECTED_DEFAULT_PAGE_SIZE; - const LAST_PAGE_NUMBER = Math.ceil(EXPECTED_FIELD_COUNT / EXPECTED_DEFAULT_PAGE_SIZE); before(function () { return PageObjects.settings.navigateTo() @@ -94,30 +110,6 @@ export default function ({ getService, getPageObjects }) { }); }); }); - - it('should have correct default page size selected', function () { - return PageObjects.settings.getPageSize() - .then(function (pageSize) { - expect(pageSize).to.be('Rows per page: ' + EXPECTED_DEFAULT_PAGE_SIZE); - }); - }); - - it('should have the correct number of rows per page', async function () { - for (let pageNum = 1; pageNum <= LAST_PAGE_NUMBER; pageNum += 1) { - if (pageNum > 1) { - // We are by default on page 1 so don't navigate there - await PageObjects.settings.goToPage(pageNum); - } - - const pageFieldNames = await retry.tryMethod(PageObjects.settings, 'getFieldNames'); - - if (pageNum === LAST_PAGE_NUMBER) { - expect(pageFieldNames).to.have.length(EXPECTED_LAST_PAGE_COUNT); - } else { - expect(pageFieldNames).to.have.length(EXPECTED_DEFAULT_PAGE_SIZE); - } - } - }); }); // end describe pagination }); // end index result field sort } diff --git a/test/functional/apps/management/_kibana_settings.js b/test/functional/apps/management/_kibana_settings.js index 31b6d8aa7a6ecc..602a3ca276f7a4 100644 --- a/test/functional/apps/management/_kibana_settings.js +++ b/test/functional/apps/management/_kibana_settings.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -28,18 +47,11 @@ export default function ({ getService, getPageObjects }) { expect(advancedSetting).to.be('America/Phoenix'); }); - it('should coerce an empty setting of type JSON into an empty object', async function () { - await PageObjects.settings.clickKibanaSettings(); - await PageObjects.settings.setAdvancedSettingsInput('query:queryString:options', '', 'unsavedValueJsonTextArea'); - const advancedSetting = await PageObjects.settings.getAdvancedSettings('query:queryString:options'); - expect(advancedSetting).to.be.eql('{}'); - }); - describe('state:storeInSessionStorage', () => { it ('defaults to false', async () => { await PageObjects.settings.clickKibanaSettings(); - const storeInSessionStorage = await PageObjects.settings.getAdvancedSettings('state:storeInSessionStorage'); - expect(storeInSessionStorage).to.be('false'); + const storeInSessionStorage = await PageObjects.settings.getAdvancedSettingCheckbox('state:storeInSessionStorage'); + expect(storeInSessionStorage).to.be(false); }); it('when false, dashboard state is unhashed', async function () { @@ -61,8 +73,8 @@ export default function ({ getService, getPageObjects }) { await PageObjects.settings.navigateTo(); await PageObjects.settings.clickKibanaSettings(); await PageObjects.settings.toggleAdvancedSettingCheckbox('state:storeInSessionStorage'); - const storeInSessionStorage = await PageObjects.settings.getAdvancedSettings('state:storeInSessionStorage'); - expect(storeInSessionStorage).to.be('true'); + const storeInSessionStorage = await PageObjects.settings.getAdvancedSettingCheckbox('state:storeInSessionStorage'); + expect(storeInSessionStorage).to.be(true); }); it('when true, dashboard state is hashed', async function () { @@ -87,21 +99,6 @@ export default function ({ getService, getPageObjects }) { }); }); - describe('notifications:banner', () => { - it('Should convert notification banner markdown into HTML', async function () { - await PageObjects.settings.clickKibanaSettings(); - await PageObjects.settings.setAdvancedSettingsInput('notifications:banner', '# Welcome to Kibana', 'unsavedValueMarkdownTextArea'); - const bannerValue = await PageObjects.settings.getAdvancedSettings('notifications:banner'); - expect(bannerValue).to.equal('Welcome to Kibana'); - }); - - after('navigate to settings page and clear notifications:banner', async () => { - await PageObjects.settings.navigateTo(); - await PageObjects.settings.clickKibanaSettings(); - await PageObjects.settings.clearAdvancedSettings('notifications:banner'); - }); - }); - after(async function () { await PageObjects.settings.clickKibanaSettings(); await PageObjects.settings.setAdvancedSettingsSelect('dateFormat:tz', 'UTC'); diff --git a/test/functional/apps/management/_scripted_fields.js b/test/functional/apps/management/_scripted_fields.js index 12f042d5ca8489..eb52c2a3d88d70 100644 --- a/test/functional/apps/management/_scripted_fields.js +++ b/test/functional/apps/management/_scripted_fields.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + // Tests for 4 scripted fields; // 1. Painless (number type) // 2. Painless (string type) diff --git a/test/functional/apps/management/_scripted_fields_filter.js b/test/functional/apps/management/_scripted_fields_filter.js index b3842950f6f9c2..3e0e02617233d0 100644 --- a/test/functional/apps/management/_scripted_fields_filter.js +++ b/test/functional/apps/management/_scripted_fields_filter.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; diff --git a/test/functional/apps/management/_test_huge_fields.js b/test/functional/apps/management/_test_huge_fields.js index dfa3017c658e05..0dc402f06a72d7 100644 --- a/test/functional/apps/management/_test_huge_fields.js +++ b/test/functional/apps/management/_test_huge_fields.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/management/exports/_import_objects_with_index_patterns.json b/test/functional/apps/management/exports/_import_objects_with_index_patterns.json new file mode 100644 index 00000000000000..9b90f16ad8993f --- /dev/null +++ b/test/functional/apps/management/exports/_import_objects_with_index_patterns.json @@ -0,0 +1,31 @@ +[ + { + "_id": "f1e4c910-a2e6-11e7-bb30-233be9be6a15", + "_type": "index-pattern", + "_source": { + "title": "logstash-*", + "timeFieldName": "@timestamp", + "fields": "[{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":true,\"doc_values\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"analyzed\":false,\"doc_values\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":false,\"analyzed\":false,\"doc_values\":false},{\"name\":\"expression script\",\"type\":\"number\",\"count\":0,\"scripted\":true,\"script\":\"doc['bytes'].value\",\"lang\":\"expression\",\"indexed\":true,\"analyzed\":false,\"doc_values\":false}]" + }, + "_meta": { + "savedObjectVersion": 2 + } + }, + { + "_id": "Shared-Item-Visualization-AreaChart", + "_type": "visualization", + "_source": { + "title": "Shared-Item Visualization AreaChart", + "visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}", + "uiStateJSON": "{}", + "description": "AreaChart", + "version": 1, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"index\":\"f1e4c910-a2e6-11e7-bb30-233be9be6a15\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" + } + }, + "_meta": { + "savedObjectVersion": 2 + } + } +] diff --git a/test/functional/apps/management/index.js b/test/functional/apps/management/index.js index d1f12708422330..346125b4cea89c 100644 --- a/test/functional/apps/management/index.js +++ b/test/functional/apps/management/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, loadTestFile }) { const esArchiver = getService('esArchiver'); diff --git a/test/functional/apps/status_page/index.js b/test/functional/apps/status_page/index.js index a14c2700ad61c5..2d25e200421114 100644 --- a/test/functional/apps/status_page/index.js +++ b/test/functional/apps/status_page/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/timelion/_expression_typeahead.js b/test/functional/apps/timelion/_expression_typeahead.js index 12b73a0f838ba3..9d0fb4be8c130e 100644 --- a/test/functional/apps/timelion/_expression_typeahead.js +++ b/test/functional/apps/timelion/_expression_typeahead.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getPageObjects }) { diff --git a/test/functional/apps/timelion/index.js b/test/functional/apps/timelion/index.js index c05427ddef194f..73c9375460b349 100644 --- a/test/functional/apps/timelion/index.js +++ b/test/functional/apps/timelion/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, loadTestFile }) { const remote = getService('remote'); const log = getService('log'); diff --git a/test/functional/apps/visualize/_area_chart.js b/test/functional/apps/visualize/_area_chart.js index 0af9f0237c5d82..0516dd5238d2e1 100644 --- a/test/functional/apps/visualize/_area_chart.js +++ b/test/functional/apps/visualize/_area_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_chart_types.js b/test/functional/apps/visualize/_chart_types.js index 556f2ea32e9184..eb1e0d1e21fd34 100644 --- a/test/functional/apps/visualize/_chart_types.js +++ b/test/functional/apps/visualize/_chart_types.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_data_table.js b/test/functional/apps/visualize/_data_table.js index 60e2738b45ecda..ae1c7660117b43 100644 --- a/test/functional/apps/visualize/_data_table.js +++ b/test/functional/apps/visualize/_data_table.js @@ -1,8 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { const log = getService('log'); const retry = getService('retry'); + const filterBar = getService('filterBar'); const PageObjects = getPageObjects(['common', 'visualize', 'header']); describe('visualize app', function describeIndexTests() { @@ -91,6 +111,34 @@ export default function ({ getService, getPageObjects }) { }); }); + it('should show correct data for a data table with date histogram', async () => { + await PageObjects.common.navigateToUrl('visualize', 'new'); + await PageObjects.visualize.clickDataTable(); + await PageObjects.visualize.clickNewSearch(); + await PageObjects.header.setAbsoluteRange(fromTime, toTime); + await PageObjects.visualize.clickBucket('Split Rows'); + await PageObjects.visualize.selectAggregation('Date Histogram'); + await PageObjects.visualize.selectField('@timestamp'); + await PageObjects.visualize.setInterval('Daily'); + await PageObjects.visualize.clickGo(); + await PageObjects.header.waitUntilLoadingHasFinished(); + const data = await PageObjects.visualize.getDataTableData(); + expect(data.trim().split('\n')).to.be.eql([ + '2015-09-20', '4,757', + '2015-09-21', '4,614', + '2015-09-22', '4,633', + ]); + }); + + it('should correctly filter for applied time filter on the main timefield', async () => { + await filterBar.addFilter('@timestamp', 'is between', ['2015-09-19', '2015-09-21']); + await PageObjects.header.waitUntilLoadingHasFinished(); + const data = await PageObjects.visualize.getDataTableData(); + expect(data.trim().split('\n')).to.be.eql([ + '2015-09-20', '4,757', + ]); + }); + }); }); } diff --git a/test/functional/apps/visualize/_experimental_vis.js b/test/functional/apps/visualize/_experimental_vis.js index 4deed63aa7766a..984fd9e7bb15f4 100644 --- a/test/functional/apps/visualize/_experimental_vis.js +++ b/test/functional/apps/visualize/_experimental_vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default ({ getService, getPageObjects }) => { diff --git a/test/functional/apps/visualize/_gauge_chart.js b/test/functional/apps/visualize/_gauge_chart.js index a9bcd4786007e5..0b40f80c62b185 100644 --- a/test/functional/apps/visualize/_gauge_chart.js +++ b/test/functional/apps/visualize/_gauge_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_heatmap_chart.js b/test/functional/apps/visualize/_heatmap_chart.js index 8a2a3bb31a6248..d4bd451dd54396 100644 --- a/test/functional/apps/visualize/_heatmap_chart.js +++ b/test/functional/apps/visualize/_heatmap_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_histogram_request_start.js b/test/functional/apps/visualize/_histogram_request_start.js index 9bd43df8806fe1..b85d2ab49c149d 100644 --- a/test/functional/apps/visualize/_histogram_request_start.js +++ b/test/functional/apps/visualize/_histogram_request_start.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_input_control_vis.js b/test/functional/apps/visualize/_input_control_vis.js index aa0d3680311714..57797f72333fc1 100644 --- a/test/functional/apps/visualize/_input_control_vis.js +++ b/test/functional/apps/visualize/_input_control_vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -16,9 +35,9 @@ export default function ({ getService, getPageObjects }) { await PageObjects.header.setAbsoluteRange('2017-01-01', '2017-01-02'); await PageObjects.visualize.clickVisEditorTab('controls'); await PageObjects.visualize.addInputControl(); - await PageObjects.visualize.setReactSelect('.index-pattern-react-select', 'logstash'); + await PageObjects.visualize.setComboBox('indexPatternSelect-0', 'logstash'); await PageObjects.common.sleep(1000); // give time for index-pattern to be fetched - await PageObjects.visualize.setReactSelect('.field-react-select', FIELD_NAME); + await PageObjects.visualize.setComboBox('fieldSelect-0', FIELD_NAME); await PageObjects.visualize.clickGo(); await PageObjects.header.waitUntilLoadingHasFinished(); @@ -34,7 +53,7 @@ export default function ({ getService, getPageObjects }) { describe('updateFiltersOnChange is false', () => { it('should contain dropdown with terms aggregation results as options', async () => { - const menu = await PageObjects.visualize.getReactSelectOptions('inputControl0'); + const menu = await PageObjects.visualize.getComboBoxOptions('listControlSelect0'); expect(menu.trim().split('\n').join()).to.equal('ios,osx,win 7,win 8,win xp'); }); @@ -48,10 +67,10 @@ export default function ({ getService, getPageObjects }) { }); it('should stage filter when item selected but not create filter pill', async () => { - await PageObjects.visualize.setReactSelect('.list-control-react-select', 'ios'); + await PageObjects.visualize.setComboBox('listControlSelect0', 'ios'); - const dropdownValue = await PageObjects.visualize.getReactSelectValue('.list-control-react-select'); - expect(dropdownValue.trim()).to.equal('ios'); + const selectedOptions = await PageObjects.visualize.getComboBoxSelectedOptions('listControlSelect0'); + expect(selectedOptions[0].trim()).to.equal('ios'); const hasFilter = await filterBar.hasFilter(FIELD_NAME, 'ios'); expect(hasFilter).to.equal(false); @@ -65,8 +84,8 @@ export default function ({ getService, getPageObjects }) { }); it('should replace existing filter pill(s) when new item is selected', async () => { - await PageObjects.visualize.clearReactSelect('.list-control-react-select'); - await PageObjects.visualize.setReactSelect('.list-control-react-select', 'osx'); + await PageObjects.visualize.clearComboBox('listControlSelect0'); + await PageObjects.visualize.setComboBox('listControlSelect0', 'osx'); await testSubjects.click('inputControlSubmitBtn'); const hasOldFilter = await filterBar.hasFilter(FIELD_NAME, 'ios'); @@ -79,18 +98,18 @@ export default function ({ getService, getPageObjects }) { await filterBar.removeFilter(FIELD_NAME); await PageObjects.common.sleep(500); // give time for filter to be removed and event handlers to fire - const hasValue = await PageObjects.visualize.doesReactSelectHaveValue('.list-control-react-select'); + const hasValue = await PageObjects.visualize.doesComboBoxHaveSelectedOptions('listControlSelect0'); expect(hasValue).to.equal(false); }); it('should clear form when Clear button is clicked but not remove filter pill', async () => { - await PageObjects.visualize.setReactSelect('.list-control-react-select', 'ios'); + await PageObjects.visualize.setComboBox('listControlSelect0', 'ios'); await testSubjects.click('inputControlSubmitBtn'); const hasFilterBeforeClearBtnClicked = await filterBar.hasFilter(FIELD_NAME, 'ios'); expect(hasFilterBeforeClearBtnClicked).to.equal(true); await testSubjects.click('inputControlClearBtn'); - const hasValue = await PageObjects.visualize.doesReactSelectHaveValue('.list-control-react-select'); + const hasValue = await PageObjects.visualize.doesComboBoxHaveSelectedOptions('listControlSelect0'); expect(hasValue).to.equal(false); const hasFilterAfterClearBtnClicked = await filterBar.hasFilter(FIELD_NAME, 'ios'); @@ -131,10 +150,10 @@ export default function ({ getService, getPageObjects }) { }); it('should add filter pill when item selected', async () => { - await PageObjects.visualize.setReactSelect('.list-control-react-select', 'ios'); + await PageObjects.visualize.setComboBox('listControlSelect0', 'ios'); - const dropdownValue = await PageObjects.visualize.getReactSelectValue('.list-control-react-select'); - expect(dropdownValue.trim()).to.equal('ios'); + const selectedOptions = await PageObjects.visualize.getComboBoxSelectedOptions('listControlSelect0'); + expect(selectedOptions[0].trim()).to.equal('ios'); const hasFilter = await filterBar.hasFilter(FIELD_NAME, 'ios'); expect(hasFilter).to.equal(true); @@ -159,7 +178,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); // Expect control to have values for selected time filter - const menu = await PageObjects.visualize.getReactSelectOptions('inputControl0'); + const menu = await PageObjects.visualize.getComboBoxOptions('listControlSelect0'); expect(menu.trim().split('\n').join()).to.equal('osx,win 7,win 8,win xp'); }); }); @@ -172,14 +191,14 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualize.clickVisEditorTab('controls'); await PageObjects.visualize.addInputControl(); - await PageObjects.visualize.setReactSelect('#indexPatternSelect-0-row', 'logstash'); + await PageObjects.visualize.setComboBox('indexPatternSelect-0', 'logstash'); await PageObjects.common.sleep(1000); // give time for index-pattern to be fetched - await PageObjects.visualize.setReactSelect('#fieldSelect-0-row', 'geo.src'); + await PageObjects.visualize.setComboBox('fieldSelect-0', 'geo.src'); await PageObjects.visualize.addInputControl(); - await PageObjects.visualize.setReactSelect('#indexPatternSelect-1-row', 'logstash'); + await PageObjects.visualize.setComboBox('indexPatternSelect-1', 'logstash'); await PageObjects.common.sleep(1000); // give time for index-pattern to be fetched - await PageObjects.visualize.setReactSelect('#fieldSelect-1-row', 'clientip'); + await PageObjects.visualize.setComboBox('fieldSelect-1', 'clientip'); await PageObjects.visualize.setSelectByOptionText('parentSelect-1', 'geo.src'); await PageObjects.visualize.clickGo(); @@ -187,7 +206,7 @@ export default function ({ getService, getPageObjects }) { }); it('should disable child control when parent control is not set', async () => { - const parentControlMenu = await PageObjects.visualize.getReactSelectOptions('inputControl0'); + const parentControlMenu = await PageObjects.visualize.getComboBoxOptions('listControlSelect0'); expect(parentControlMenu.trim().split('\n').join()).to.equal('BR,CN,ID,IN,US'); const childControlInput = await find.byCssSelector('[data-test-subj="inputControl1"] input'); @@ -196,14 +215,14 @@ export default function ({ getService, getPageObjects }) { }); it('should filter child control options by parent control value', async () => { - await PageObjects.visualize.setReactSelect('[data-test-subj="inputControl0"]', 'BR'); + await PageObjects.visualize.setComboBox('listControlSelect0', 'BR'); - const childControlMenu = await PageObjects.visualize.getReactSelectOptions('inputControl1'); + const childControlMenu = await PageObjects.visualize.getComboBoxOptions('listControlSelect1'); expect(childControlMenu.trim().split('\n').join()).to.equal('14.61.182.136,3.174.21.181,6.183.121.70,71.241.97.89,9.69.255.135'); }); it('should create a seperate filter pill for parent control and child control', async () => { - await PageObjects.visualize.setReactSelect('[data-test-subj="inputControl1"]', '14.61.182.136'); + await PageObjects.visualize.setComboBox('listControlSelect1', '14.61.182.136'); await testSubjects.click('inputControlSubmitBtn'); @@ -215,7 +234,7 @@ export default function ({ getService, getPageObjects }) { }); it('should clear child control dropdown when parent control value is removed', async () => { - await PageObjects.visualize.clearReactSelect('[data-test-subj="inputControl0"]'); + await PageObjects.visualize.clearComboBox('listControlSelect0'); await PageObjects.common.sleep(500); // give time for filter to be removed and event handlers to fire const childControlInput = await find.byCssSelector('[data-test-subj="inputControl1"] input'); @@ -229,7 +248,7 @@ export default function ({ getService, getPageObjects }) { await filterBar.removeFilter('geo.src'); await PageObjects.common.sleep(500); // give time for filter to be removed and event handlers to fire - const hasValue = await PageObjects.visualize.doesReactSelectHaveValue('[data-test-subj="inputControl1"]'); + const hasValue = await PageObjects.visualize.doesComboBoxHaveSelectedOptions('listControlSelect0'); expect(hasValue).to.equal(false); }); }); diff --git a/test/functional/apps/visualize/_lab_mode.js b/test/functional/apps/visualize/_lab_mode.js index 4bf9bc0e50a3ae..6c8a79b9fe0355 100644 --- a/test/functional/apps/visualize/_lab_mode.js +++ b/test/functional/apps/visualize/_lab_mode.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_line_chart.js b/test/functional/apps/visualize/_line_chart.js index 40b293c58e83c6..e76709c7df2ca5 100644 --- a/test/functional/apps/visualize/_line_chart.js +++ b/test/functional/apps/visualize/_line_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -87,7 +106,7 @@ export default function ({ getService, getPageObjects }) { const expectedChartData = ['png 1,373', 'php 445', 'jpg 9,109', 'gif 918', 'css 2,159']; log.debug('Order By = Term'); - return PageObjects.visualize.selectOrderBy('_term') + return PageObjects.visualize.selectOrderBy('_key') .then(function clickGo() { return PageObjects.visualize.clickGo(); }) diff --git a/test/functional/apps/visualize/_markdown_vis.js b/test/functional/apps/visualize/_markdown_vis.js index 56e604da063949..fbd891ab6fefba 100644 --- a/test/functional/apps/visualize/_markdown_vis.js +++ b/test/functional/apps/visualize/_markdown_vis.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getPageObjects, getService }) { diff --git a/test/functional/apps/visualize/_metric_chart.js b/test/functional/apps/visualize/_metric_chart.js index 8e0f6a0bed61df..04c5a9cc561126 100644 --- a/test/functional/apps/visualize/_metric_chart.js +++ b/test/functional/apps/visualize/_metric_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_pie_chart.js b/test/functional/apps/visualize/_pie_chart.js index 934fc1f3273b4f..e77580995aa151 100644 --- a/test/functional/apps/visualize/_pie_chart.js +++ b/test/functional/apps/visualize/_pie_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_point_series_options.js b/test/functional/apps/visualize/_point_series_options.js index 233e6229f9a40b..128e1b026760b3 100644 --- a/test/functional/apps/visualize/_point_series_options.js +++ b/test/functional/apps/visualize/_point_series_options.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -75,7 +94,7 @@ export default function ({ getService, getPageObjects }) { return PageObjects.visualize.clickGo(); }) .then(function () { - return PageObjects.header.isGlobalLoadingIndicatorHidden(); + return PageObjects.header.awaitGlobalLoadingIndicatorHidden(); }); }); diff --git a/test/functional/apps/visualize/_region_map.js b/test/functional/apps/visualize/_region_map.js index c394588ebe2acf..7106802d7f6120 100644 --- a/test/functional/apps/visualize/_region_map.js +++ b/test/functional/apps/visualize/_region_map.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; diff --git a/test/functional/apps/visualize/_shared_item.js b/test/functional/apps/visualize/_shared_item.js index 6be57dedb234e1..0b5b46a76cf1d2 100644 --- a/test/functional/apps/visualize/_shared_item.js +++ b/test/functional/apps/visualize/_shared_item.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_spy_panel.js b/test/functional/apps/visualize/_spy_panel.js index 963e1c02d60cd8..d9d729410ca9e9 100644 --- a/test/functional/apps/visualize/_spy_panel.js +++ b/test/functional/apps/visualize/_spy_panel.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_tag_cloud.js b/test/functional/apps/visualize/_tag_cloud.js index a22404f3451251..0cec60229a3bbe 100644 --- a/test/functional/apps/visualize/_tag_cloud.js +++ b/test/functional/apps/visualize/_tag_cloud.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -43,7 +62,7 @@ export default function ({ getService, getPageObjects }) { }); }) .then(function () { - return PageObjects.visualize.selectOrderBy('_term'); + return PageObjects.visualize.selectOrderBy('_key'); }) .then(function () { return PageObjects.visualize.clickGo(); diff --git a/test/functional/apps/visualize/_tile_map.js b/test/functional/apps/visualize/_tile_map.js index c193a417738665..f3400180d94bb8 100644 --- a/test/functional/apps/visualize/_tile_map.js +++ b/test/functional/apps/visualize/_tile_map.js @@ -1,175 +1,236 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { const log = getService('log'); const retry = getService('retry'); + const remote = getService('remote'); const PageObjects = getPageObjects(['common', 'visualize', 'header', 'settings']); - describe('tile map visualize app', function describeIndexTests() { - before(async function () { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; - - log.debug('navigateToApp visualize'); - await PageObjects.common.navigateToUrl('visualize', 'new'); - log.debug('clickTileMap'); - await PageObjects.visualize.clickTileMap(); - await PageObjects.visualize.clickNewSearch(); - log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"'); - await PageObjects.header.setAbsoluteRange(fromTime, toTime); - log.debug('select bucket Geo Coordinates'); - await PageObjects.visualize.clickBucket('Geo Coordinates'); - log.debug('Click aggregation Geohash'); - await PageObjects.visualize.selectAggregation('Geohash'); - log.debug('Click field geo.coordinates'); - await retry.try(async function tryingForTime() { - await PageObjects.visualize.selectField('geo.coordinates'); - }); - await PageObjects.visualize.clickGo(); - await PageObjects.header.waitUntilLoadingHasFinished(); - }); - /** - * manually compare data due to possible small difference in numbers. This is browser dependent. - */ - function compareTableData(expected, actual) { - log.debug('comparing expected: ', expected); - log.debug('with actual: ', actual); - - expect(actual.length).to.eql(expected.length); - - function tokenize(row) { - const tokens = row.split(' '); - - let geohashIndex; - let countIndex; - let latIndex; - let lonIndex; - if (tokens.length === 8) { - // table row aggregations: geohash_grid -> count -> geocentroid - geohashIndex = 0; - countIndex = 1; - latIndex = 4; - lonIndex = 6; - } else if (tokens.length === 9) { - // table row aggregations: filter -> geohash_grid -> count -> geocentroid - geohashIndex = 1; - countIndex = 2; - latIndex = 5; - lonIndex = 7; - } else { - log.error(`Unexpected number of tokens contained in spy table row: ${row}`); - } - return { - geohash: tokens[geohashIndex], - count: tokens[countIndex], - lat: Math.floor(parseFloat(tokens[latIndex])), - lon: Math.floor(parseFloat(tokens[lonIndex])) - }; - } + describe('tile map visualize app', function () { - expect(actual.map(tokenize)).to.eql(expected.map(tokenize)); - } - describe('Only request data around extent of map option', async () => { - before(async () => await PageObjects.visualize.openSpyPanel()); + describe('incomplete config', function describeIndexTests() { - it('when checked adds filters to aggregation', async () => { - const tableHeaders = await PageObjects.visualize.getDataTableHeaders(); - expect(tableHeaders.trim()).to.equal('filter geohash_grid Count Geo Centroid'); - }); - it('when not checked does not add filters to aggregation', async () => { - await PageObjects.visualize.toggleIsFilteredByCollarCheckbox(); - await PageObjects.visualize.clickGo(); - await PageObjects.header.waitUntilLoadingHasFinished(); - const tableHeaders = await PageObjects.visualize.getDataTableHeaders(); - expect(tableHeaders.trim()).to.equal('geohash_grid Count Geo Centroid'); - }); + before(async function () { + // Make sure the window is height enough to show the spy panel without hiding the map + remote.setWindowSize(1280, 1000); - after(async () => { - await PageObjects.visualize.closeSpyPanel(); - await PageObjects.visualize.toggleIsFilteredByCollarCheckbox(); - await PageObjects.visualize.clickGo(); - await PageObjects.header.waitUntilLoadingHasFinished(); - }); - }); + const fromTime = '2015-09-19 06:31:44.000'; + const toTime = '2015-09-23 18:31:44.000'; - describe('tile map chart', function indexPatternCreation() { - it('should display spy panel toggle button', async function () { - const spyToggleExists = await PageObjects.visualize.getSpyToggleExists(); - expect(spyToggleExists).to.be(true); - }); + log.debug('navigateToApp visualize'); + await PageObjects.common.navigateToUrl('visualize', 'new'); + log.debug('clickTileMap'); + await PageObjects.visualize.clickTileMap(); + await PageObjects.visualize.clickNewSearch(); + log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"'); + await PageObjects.header.setAbsoluteRange(fromTime, toTime); - it('should show correct tile map data on default zoom level', async function () { - const expectedTableData = ['9 5,787 { "lat": 37.22448418632405, "lon": -103.01935195013255 }', - 'd 5,600 { "lat": 37.44271478370398, "lon": -81.72692197253595 }', - 'c 1,319 { "lat": 47.72720855392425, "lon": -109.84745063951028 }', - 'b 999 { "lat": 62.04130042948433, "lon": -155.28087269195967 }', - 'f 187 { "lat": 45.656166475784175, "lon": -82.45831044201545 }', - '8 108 { "lat": 18.85260305600241, "lon": -156.5148810390383 }']; - //level 1 - await PageObjects.visualize.clickMapZoomOut(); - //level 0 - await PageObjects.visualize.clickMapZoomOut(); - - await PageObjects.visualize.openSpyPanel(); - await PageObjects.visualize.setSpyPanelPageSize('All'); - await PageObjects.visualize.selectTableInSpyPaneSelect(); - const actualTableData = await PageObjects.visualize.getDataTableData(); - compareTableData(expectedTableData, actualTableData.trim().split('\n')); - await PageObjects.visualize.closeSpyPanel(); + //do not configure aggs }); - it('should not be able to zoom out beyond 0', async function () { - await PageObjects.visualize.zoomAllTheWayOut(); - const enabled = await PageObjects.visualize.getMapZoomOutEnabled(); - expect(enabled).to.be(false); - }); - // See https://github.com/elastic/kibana/issues/13137 if this test starts failing intermittently - it('Fit data bounds should zoom to level 3', async function () { - const expectedPrecision2DataTable = [ - '- dn 1,429 { "lat": 36.38058884214008, "lon": -84.78904345856186 }', - '- dp 1,418 { "lat": 41.64735764514311, "lon": -84.89821054446622 }', - '- 9y 1,215 { "lat": 36.45605112115542, "lon": -95.0664575824997 }', - '- 9z 1,099 { "lat": 42.18533764798381, "lon": -95.16736779696697 }', - '- dr 1,076 { "lat": 42.02351013780139, "lon": -73.98091798822212 }', - '- dj 982 { "lat": 31.672735499211466, "lon": -84.50815450245526 }', - '- 9v 938 { "lat": 31.380767446489873, "lon": -95.2705099188121 }', - '- 9q 722 { "lat": 36.51360723008776, "lon": -119.18302692440686 }', - '- 9w 475 { "lat": 36.39264289740669, "lon": -106.91102287667363 }', - '- cb 457 { "lat": 46.70940601270996, "lon": -95.81077801137022 }' - ]; - - await PageObjects.visualize.clickMapFitDataBounds(); - await PageObjects.visualize.openSpyPanel(); - await PageObjects.visualize.selectTableInSpyPaneSelect(); - const data = await PageObjects.visualize.getDataTableData(); - await compareTableData(expectedPrecision2DataTable, data.trim().split('\n')); - await PageObjects.visualize.closeSpyPanel(); + it('should be able to zoom in twice', async () => { + //should not throw + await PageObjects.visualize.clickMapZoomIn(); + await PageObjects.visualize.clickMapZoomIn(); }); - it('Newly saved visualization retains map bounds', async () => { - const vizName1 = 'Visualization TileMap'; - await PageObjects.visualize.clickMapZoomIn(); - await PageObjects.visualize.clickMapZoomIn(); + }); + + - const mapBounds = await PageObjects.visualize.getMapBounds(); + describe('complete config', function describeIndexTests() { + before(async function () { + // Make sure the window is height enough to show the spy panel without hiding the map + remote.setWindowSize(1280, 1000); + + const fromTime = '2015-09-19 06:31:44.000'; + const toTime = '2015-09-23 18:31:44.000'; + + log.debug('navigateToApp visualize'); + await PageObjects.common.navigateToUrl('visualize', 'new'); + log.debug('clickTileMap'); + await PageObjects.visualize.clickTileMap(); + await PageObjects.visualize.clickNewSearch(); + log.debug('Set absolute time range from \"' + fromTime + '\" to \"' + toTime + '\"'); + await PageObjects.header.setAbsoluteRange(fromTime, toTime); + log.debug('select bucket Geo Coordinates'); + await PageObjects.visualize.clickBucket('Geo Coordinates'); + log.debug('Click aggregation Geohash'); + await PageObjects.visualize.selectAggregation('Geohash'); + log.debug('Click field geo.coordinates'); + await retry.try(async function tryingForTime() { + await PageObjects.visualize.selectField('geo.coordinates'); + }); + await PageObjects.visualize.clickGo(); + await PageObjects.header.waitUntilLoadingHasFinished(); + }); - await PageObjects.visualize.closeSpyPanel(); - await PageObjects.visualize.saveVisualization(vizName1); + /** + * manually compare data due to possible small difference in numbers. This is browser dependent. + */ + function compareTableData(expected, actual) { + log.debug('comparing expected: ', expected); + log.debug('with actual: ', actual); + + expect(actual.length).to.eql(expected.length); + + function tokenize(row) { + const tokens = row.split(' '); + + let geohashIndex; + let countIndex; + let latIndex; + let lonIndex; + if (tokens.length === 8) { + // table row aggregations: geohash_grid -> count -> geocentroid + geohashIndex = 0; + countIndex = 1; + latIndex = 4; + lonIndex = 6; + } else if (tokens.length === 9) { + // table row aggregations: filter -> geohash_grid -> count -> geocentroid + geohashIndex = 1; + countIndex = 2; + latIndex = 5; + lonIndex = 7; + } else { + log.error(`Unexpected number of tokens contained in spy table row: ${row}`); + } + return { + geohash: tokens[geohashIndex], + count: tokens[countIndex], + lat: Math.floor(parseFloat(tokens[latIndex])), + lon: Math.floor(parseFloat(tokens[lonIndex])) + }; + } - const afterSaveMapBounds = await PageObjects.visualize.getMapBounds(); + expect(actual.map(tokenize)).to.eql(expected.map(tokenize)); + } - // For some reason the values are slightly different, so we can't check that they are equal. But we did - // have a bug where after the save, there were _no_ map bounds. So this checks for the later case, but - // until we figure out how to make sure the map center is always the exact same, we can't comparison check. - expect(mapBounds).to.not.be(undefined); - expect(afterSaveMapBounds).to.not.be(undefined); + describe('Only request data around extent of map option', async () => { + before(async () => await PageObjects.visualize.openSpyPanel()); + + it('when checked adds filters to aggregation', async () => { + const tableHeaders = await PageObjects.visualize.getDataTableHeaders(); + expect(tableHeaders.trim()).to.equal('filter geohash_grid Count Geo Centroid'); + }); + + it('when not checked does not add filters to aggregation', async () => { + await PageObjects.visualize.toggleIsFilteredByCollarCheckbox(); + await PageObjects.visualize.clickGo(); + await PageObjects.header.waitUntilLoadingHasFinished(); + const tableHeaders = await PageObjects.visualize.getDataTableHeaders(); + expect(tableHeaders.trim()).to.equal('geohash_grid Count Geo Centroid'); + }); + + after(async () => { + await PageObjects.visualize.closeSpyPanel(); + await PageObjects.visualize.toggleIsFilteredByCollarCheckbox(); + await PageObjects.visualize.clickGo(); + await PageObjects.header.waitUntilLoadingHasFinished(); + }); }); + describe('tile map chart', function indexPatternCreation() { + it('should display spy panel toggle button', async function () { + const spyToggleExists = await PageObjects.visualize.getSpyToggleExists(); + expect(spyToggleExists).to.be(true); + }); + + it('should show correct tile map data on default zoom level', async function () { + const expectedTableData = ['9 5,787 { "lat": 37.22448418632405, "lon": -103.01935195013255 }', + 'd 5,600 { "lat": 37.44271478370398, "lon": -81.72692197253595 }', + 'c 1,319 { "lat": 47.72720855392425, "lon": -109.84745063951028 }', + 'b 999 { "lat": 62.04130042948433, "lon": -155.28087269195967 }', + 'f 187 { "lat": 45.656166475784175, "lon": -82.45831044201545 }', + '8 108 { "lat": 18.85260305600241, "lon": -156.5148810390383 }']; + //level 1 + await PageObjects.visualize.clickMapZoomOut(); + //level 0 + await PageObjects.visualize.clickMapZoomOut(); + + await PageObjects.visualize.openSpyPanel(); + await PageObjects.visualize.setSpyPanelPageSize('All'); + await PageObjects.visualize.selectTableInSpyPaneSelect(); + const actualTableData = await PageObjects.visualize.getDataTableData(); + compareTableData(expectedTableData, actualTableData.trim().split('\n')); + await PageObjects.visualize.closeSpyPanel(); + }); + + it('should not be able to zoom out beyond 0', async function () { + await PageObjects.visualize.zoomAllTheWayOut(); + const enabled = await PageObjects.visualize.getMapZoomOutEnabled(); + expect(enabled).to.be(false); + }); + + // See https://github.com/elastic/kibana/issues/13137 if this test starts failing intermittently + it('Fit data bounds should zoom to level 3', async function () { + const expectedPrecision2DataTable = [ + '- dn 1,429 { "lat": 36.38058884214008, "lon": -84.78904345856186 }', + '- dp 1,418 { "lat": 41.64735764514311, "lon": -84.89821054446622 }', + '- 9y 1,215 { "lat": 36.45605112115542, "lon": -95.0664575824997 }', + '- 9z 1,099 { "lat": 42.18533764798381, "lon": -95.16736779696697 }', + '- dr 1,076 { "lat": 42.02351013780139, "lon": -73.98091798822212 }', + '- dj 982 { "lat": 31.672735499211466, "lon": -84.50815450245526 }', + '- 9v 938 { "lat": 31.380767446489873, "lon": -95.2705099188121 }', + '- 9q 722 { "lat": 36.51360723008776, "lon": -119.18302692440686 }', + '- 9w 475 { "lat": 36.39264289740669, "lon": -106.91102287667363 }', + '- cb 457 { "lat": 46.70940601270996, "lon": -95.81077801137022 }' + ]; + + await PageObjects.visualize.clickMapFitDataBounds(); + await PageObjects.visualize.openSpyPanel(); + await PageObjects.visualize.selectTableInSpyPaneSelect(); + const data = await PageObjects.visualize.getDataTableData(); + await compareTableData(expectedPrecision2DataTable, data.trim().split('\n')); + await PageObjects.visualize.closeSpyPanel(); + }); + + it('Newly saved visualization retains map bounds', async () => { + const vizName1 = 'Visualization TileMap'; + + await PageObjects.visualize.clickMapZoomIn(); + await PageObjects.visualize.clickMapZoomIn(); + + const mapBounds = await PageObjects.visualize.getMapBounds(); + + await PageObjects.visualize.closeSpyPanel(); + await PageObjects.visualize.saveVisualization(vizName1); + + const afterSaveMapBounds = await PageObjects.visualize.getMapBounds(); + + // For some reason the values are slightly different, so we can't check that they are equal. But we did + // have a bug where after the save, there were _no_ map bounds. So this checks for the later case, but + // until we figure out how to make sure the map center is always the exact same, we can't comparison check. + expect(mapBounds).to.not.be(undefined); + expect(afterSaveMapBounds).to.not.be(undefined); + }); + + }); }); }); } diff --git a/test/functional/apps/visualize/_tsvb_chart.js b/test/functional/apps/visualize/_tsvb_chart.js index e57acfd5c98300..1225cdcb01190b 100644 --- a/test/functional/apps/visualize/_tsvb_chart.js +++ b/test/functional/apps/visualize/_tsvb_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_vega_chart.js b/test/functional/apps/visualize/_vega_chart.js index a9bf6c3f4e63c6..aad1e36efb1473 100644 --- a/test/functional/apps/visualize/_vega_chart.js +++ b/test/functional/apps/visualize/_vega_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { diff --git a/test/functional/apps/visualize/_vertical_bar_chart.js b/test/functional/apps/visualize/_vertical_bar_chart.js index d4ee320e2647a2..b157626b3108b6 100644 --- a/test/functional/apps/visualize/_vertical_bar_chart.js +++ b/test/functional/apps/visualize/_vertical_bar_chart.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export default function ({ getService, getPageObjects }) { @@ -9,7 +28,7 @@ export default function ({ getService, getPageObjects }) { const fromTime = '2015-09-19 06:31:44.000'; const toTime = '2015-09-23 18:31:44.000'; - before(function () { + const initBarChart = () => { log.debug('navigateToApp visualize'); return PageObjects.common.navigateToUrl('visualize', 'new') .then(function () { @@ -45,11 +64,13 @@ export default function ({ getService, getPageObjects }) { .then(function waitForVisualization() { return PageObjects.visualize.waitForVisualization(); }); - }); + }; describe('vertical bar chart', function indexPatternCreation() { const vizName1 = 'Visualization VerticalBarChart'; + before(initBarChart); + it('should save and load', function () { return PageObjects.visualize.saveVisualization(vizName1) .then(() => { @@ -118,5 +139,91 @@ export default function ({ getService, getPageObjects }) { }); }); }); + + describe('vertical bar with split series', function () { + before(initBarChart); + + it('should show correct series', async function () { + await PageObjects.visualize.toggleOpenEditor(2, 'false'); + await PageObjects.visualize.clickAddBucket(); + await PageObjects.visualize.clickBucket('Split Series'); + await PageObjects.visualize.selectAggregation('Terms'); + await PageObjects.visualize.selectField('response.raw'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await PageObjects.common.sleep(1003); + await PageObjects.visualize.clickGo(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const expectedEntries = ['200', '404', '503']; + const legendEntries = await PageObjects.visualize.getLegendEntries(); + expect(legendEntries).to.eql(expectedEntries); + }); + }); + + describe('vertical bar with multiple splits', function () { + before(initBarChart); + + it('should show correct series', async function () { + await PageObjects.visualize.toggleOpenEditor(2, 'false'); + await PageObjects.visualize.clickAddBucket(); + await PageObjects.visualize.clickBucket('Split Series'); + await PageObjects.visualize.selectAggregation('Terms'); + await PageObjects.visualize.selectField('response.raw'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await PageObjects.visualize.toggleOpenEditor(3, 'false'); + await PageObjects.visualize.clickAddBucket(); + await PageObjects.visualize.clickBucket('Split Series'); + await PageObjects.visualize.selectAggregation('Terms'); + await PageObjects.visualize.selectField('machine.os'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await PageObjects.common.sleep(1003); + await PageObjects.visualize.clickGo(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const expectedEntries = [ + '200 - win 8', '200 - win xp', '200 - ios', '200 - osx', '200 - win 7', + '404 - ios', '503 - ios', '503 - osx', '503 - win 7', '503 - win 8', + '503 - win xp', '404 - osx', '404 - win 7', '404 - win 8', '404 - win xp' + ]; + const legendEntries = await PageObjects.visualize.getLegendEntries(); + expect(legendEntries).to.eql(expectedEntries); + }); + + it('should show correct series when disabling first agg', async function () { + await PageObjects.visualize.toggleDisabledAgg(3); + await PageObjects.visualize.clickGo(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const expectedEntries = [ 'win 8', 'win xp', 'ios', 'osx', 'win 7' ]; + const legendEntries = await PageObjects.visualize.getLegendEntries(); + expect(legendEntries).to.eql(expectedEntries); + }); + }); + + describe('vertical bar with derivative', function () { + before(initBarChart); + + it('should show correct series', async function () { + await PageObjects.visualize.toggleOpenEditor(2, 'false'); + await PageObjects.visualize.toggleOpenEditor(1); + await PageObjects.visualize.selectAggregation('Derivative', 'metrics'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + + await PageObjects.common.sleep(1003); + await PageObjects.visualize.clickGo(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const expectedEntries = [ + 'Derivative of Count' + ]; + const legendEntries = await PageObjects.visualize.getLegendEntries(); + expect(legendEntries).to.eql(expectedEntries); + }); + + }); }); } diff --git a/test/functional/apps/visualize/index.js b/test/functional/apps/visualize/index.js index 758b1c41bf702d..ca6edba9b8bfea 100644 --- a/test/functional/apps/visualize/index.js +++ b/test/functional/apps/visualize/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, loadTestFile }) { const remote = getService('remote'); const log = getService('log'); diff --git a/test/functional/apps/xpack/index.js b/test/functional/apps/xpack/index.js index d18400a2b0def8..5b5bb60e05acb8 100644 --- a/test/functional/apps/xpack/index.js +++ b/test/functional/apps/xpack/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, getPageObjects }) { const log = getService('log'); const PageObjects = getPageObjects(['monitoring', 'settings']); diff --git a/test/functional/config.js b/test/functional/config.js index 6d94ba74718709..d63ee48913d194 100644 --- a/test/functional/config.js +++ b/test/functional/config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { CommonPageProvider, ConsolePageProvider, @@ -26,6 +45,9 @@ import { DashboardVisualizationProvider, DashboardExpectProvider, FailureDebuggingProvider, + VisualizeListingTableProvider, + DashboardAddPanelProvider, + DashboardPanelActionsProvider, } from './services'; export default async function ({ readConfigFile }) { @@ -76,8 +98,24 @@ export default async function ({ readConfigFile }) { dashboardVisualizations: DashboardVisualizationProvider, dashboardExpect: DashboardExpectProvider, failureDebugging: FailureDebuggingProvider, + visualizeListingTable: VisualizeListingTableProvider, + dashboardAddPanel: DashboardAddPanelProvider, + dashboardPanelActions: DashboardPanelActionsProvider, }, servers: commonConfig.get('servers'), + + env: commonConfig.get('env'), + + esTestCluster: commonConfig.get('esTestCluster'), + + kbnTestServer: { + ...commonConfig.get('kbnTestServer'), + serverArgs: [ + ...commonConfig.get('kbnTestServer.serverArgs'), + '--oss', + ], + }, + apps: { status_page: { pathname: '/status', diff --git a/test/functional/fixtures/es_archiver/dashboard/current/data/data.json.gz b/test/functional/fixtures/es_archiver/dashboard/current/data/data.json.gz new file mode 100644 index 00000000000000..25b0a5df46de81 Binary files /dev/null and b/test/functional/fixtures/es_archiver/dashboard/current/data/data.json.gz differ diff --git a/test/functional/fixtures/es_archiver/dashboard/current/data/mappings.json b/test/functional/fixtures/es_archiver/dashboard/current/data/mappings.json new file mode 100644 index 00000000000000..b5420238641307 --- /dev/null +++ b/test/functional/fixtures/es_archiver/dashboard/current/data/mappings.json @@ -0,0 +1,617 @@ +{ + "type": "index", + "value": { + "index": "animals-dogs-2018-01-01", + "settings": { + "index": { + "number_of_shards": "5", + "number_of_replicas": "1" + } + }, + "mappings": { + "data": { + "properties": { + "@timestamp": { + "type": "date" + }, + "animal": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "sound": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "weightLbs": { + "type": "long" + } + } + } + } + } +} + +{ + "type": "index", + "value": { + "index": "animals-dogs-2018-04-10", + "settings": { + "index": { + "number_of_shards": "5", + "number_of_replicas": "1" + } + }, + "mappings": { + "data": { + "properties": { + "@timestamp": { + "type": "date" + }, + "animal": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "sound": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "weightLbs": { + "type": "long" + } + } + } + } + } +} + +{ + "type": "index", + "value": { + "index": "animals-cats-2018-01-01", + "settings": { + "index": { + "number_of_shards": "5", + "number_of_replicas": "1" + } + }, + "mappings": { + "data": { + "properties": { + "@timestamp": { + "type": "date" + }, + "animal": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "sound": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "weightLbs": { + "type": "long" + } + } + } + } + } +} + +{ + "type": "index", + "value": { + "index": "animals-cats-2018-04-10", + "settings": { + "index": { + "number_of_shards": "5", + "number_of_replicas": "1" + } + }, + "mappings": { + "data": { + "properties": { + "@timestamp": { + "type": "date" + }, + "animal": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "sound": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "weightLbs": { + "type": "long" + } + } + } + } + } +} + +{ + "type": "index", + "value": { + "index": "dogbreeds", + "settings": { + "index": { + "number_of_shards": "5", + "number_of_replicas": "1" + } + }, + "mappings": { + "data": { + "properties": { + "activity level": { + "type": "long" + }, + "barking level": { + "type": "long" + }, + "breed": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "size": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "trainability": { + "type": "long" + } + } + } + } + } +} + +{ + "type": "index", + "value": { + "index": "logstash-0", + "settings": { + "index": { + "number_of_shards": "1", + "analysis": { + "analyzer": { + "makelogs_url": { + "type": "standard", + "max_token_length": "1000", + "tokenizer": "uax_url_email" + } + } + }, + "number_of_replicas": "0" + } + }, + "mappings": { + "doc": { + "dynamic_templates": [ + { + "string_fields": { + "match": "*", + "match_mapping_type": "string", + "mapping": { + "fields": { + "raw": { + "type": "keyword" + } + }, + "type": "text" + } + } + } + ], + "properties": { + "@message": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "@tags": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "@timestamp": { + "type": "date" + }, + "agent": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "bytes": { + "type": "long" + }, + "clientip": { + "type": "ip" + }, + "extension": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "geo": { + "properties": { + "coordinates": { + "type": "geo_point" + }, + "dest": { + "type": "keyword" + }, + "src": { + "type": "keyword" + }, + "srcdest": { + "type": "keyword" + } + } + }, + "headings": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "host": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "id": { + "type": "integer" + }, + "index": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "links": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "os": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "ram": { + "type": "long" + } + } + }, + "memory": { + "type": "double" + }, + "meta": { + "properties": { + "char": { + "type": "keyword" + }, + "related": { + "type": "text" + }, + "user": { + "properties": { + "firstname": { + "type": "text" + }, + "lastname": { + "type": "integer" + } + } + } + } + }, + "phpmemory": { + "type": "long" + }, + "referer": { + "type": "keyword" + }, + "relatedContent": { + "properties": { + "article:modified_time": { + "type": "date" + }, + "article:published_time": { + "type": "date" + }, + "article:section": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "article:tag": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "og:description": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "og:image": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "og:image:height": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "og:image:width": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "og:site_name": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "og:title": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "og:type": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "og:url": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "twitter:card": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "twitter:description": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "twitter:image": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "twitter:site": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "twitter:title": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "url": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + } + } + }, + "request": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "response": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "spaces": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "url": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + }, + "utc_time": { + "type": "date" + }, + "xss": { + "type": "text", + "fields": { + "raw": { + "type": "keyword" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz b/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz new file mode 100644 index 00000000000000..68705c9d6a2b93 Binary files /dev/null and b/test/functional/fixtures/es_archiver/dashboard/current/kibana/data.json.gz differ diff --git a/test/functional/fixtures/es_archiver/dashboard/current/kibana/mappings.json b/test/functional/fixtures/es_archiver/dashboard/current/kibana/mappings.json new file mode 100644 index 00000000000000..57a732b9f86a60 --- /dev/null +++ b/test/functional/fixtures/es_archiver/dashboard/current/kibana/mappings.json @@ -0,0 +1,274 @@ +{ + "type": "index", + "value": { + "index": ".kibana", + "settings": { + "index": { + "number_of_shards": "1", + "auto_expand_replicas": "0-1", + "number_of_replicas": "0" + } + }, + "mappings": { + "doc": { + "dynamic": "strict", + "properties": { + "config": { + "dynamic": "true", + "properties": { + "buildNum": { + "type": "keyword" + }, + "dateFormat:tz": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "defaultIndex": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "notifications:lifetime:banner": { + "type": "long" + }, + "notifications:lifetime:error": { + "type": "long" + }, + "notifications:lifetime:info": { + "type": "long" + }, + "notifications:lifetime:warning": { + "type": "long" + } + } + }, + "dashboard": { + "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" + } + } + }, + "index-pattern": { + "properties": { + "fieldFormatMap": { + "type": "text" + }, + "fields": { + "type": "text" + }, + "intervalName": { + "type": "keyword" + }, + "notExpandable": { + "type": "boolean" + }, + "sourceFilters": { + "type": "text" + }, + "timeFieldName": { + "type": "keyword" + }, + "title": { + "type": "text" + } + } + }, + "search": { + "properties": { + "columns": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "sort": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "server": { + "properties": { + "uuid": { + "type": "keyword" + } + } + }, + "timelion-sheet": { + "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" + } + } + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "url": { + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } + }, + "visualization": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchId": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + } + } + } + } + } +} diff --git a/test/functional/fixtures/es_archiver/dashboard/data.json.gz b/test/functional/fixtures/es_archiver/dashboard/legacy/data.json.gz similarity index 100% rename from test/functional/fixtures/es_archiver/dashboard/data.json.gz rename to test/functional/fixtures/es_archiver/dashboard/legacy/data.json.gz diff --git a/test/functional/fixtures/es_archiver/dashboard/mappings.json b/test/functional/fixtures/es_archiver/dashboard/legacy/mappings.json similarity index 100% rename from test/functional/fixtures/es_archiver/dashboard/mappings.json rename to test/functional/fixtures/es_archiver/dashboard/legacy/mappings.json diff --git a/test/functional/page_objects/common_page.js b/test/functional/page_objects/common_page.js index 371b7e5a9d87e8..1fa5276f22444f 100644 --- a/test/functional/page_objects/common_page.js +++ b/test/functional/page_objects/common_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { delay } from 'bluebird'; import getUrl from '../../../src/test_utils/get_url'; @@ -51,9 +70,9 @@ export function CommonPageProvider({ getService, getPageObjects }) { .then(function (defaultIndex) { if (appName === 'discover' || appName === 'visualize' || appName === 'dashboard') { if (!defaultIndex) { - // https://github.com/elastic/kibana/issues/7496 - // Even though most tests are using esClient to set the default index, sometimes Kibana clobbers - // that change. If we got here, fix it. + // https://github.com/elastic/kibana/issues/7496 + // Even though most tests are using esClient to set the default index, sometimes Kibana clobbers + // that change. If we got here, fix it. log.debug(' >>>>>>>> WARNING Navigating to [' + appName + '] with defaultIndex=' + defaultIndex); log.debug(' >>>>>>>> Setting defaultIndex to "logstash-*""'); return kibanaServer.uiSettings.update({ @@ -108,14 +127,14 @@ export function CommonPageProvider({ getService, getPageObjects }) { // Browsers don't show the ':port' if it's 80 or 443 so we have to // remove that part so we can get a match in the tests. const navSuccessful = new RegExp(appUrl.replace(':80', '').replace(':443', '') - + '.{0,' + maxAdditionalLengthOnNavUrl + '}$') + + '.{0,' + maxAdditionalLengthOnNavUrl + '}$') .test(currentUrl); if (!navSuccessful) { const msg = 'App failed to load: ' + appName + - ' in ' + defaultFindTimeout + 'ms' + - ' appUrl = ' + appUrl + - ' currentUrl = ' + currentUrl; + ' in ' + defaultFindTimeout + 'ms' + + ' appUrl = ' + appUrl + + ' currentUrl = ' + currentUrl; log.debug(msg); throw new Error(msg); } @@ -130,7 +149,7 @@ export function CommonPageProvider({ getService, getPageObjects }) { .then(function (currentUrl) { let lastUrl = currentUrl; return retry.try(function () { - // give the app time to update the URL + // give the app time to update the URL return self.sleep(501) .then(function () { return remote.getCurrentUrl(); @@ -250,6 +269,10 @@ export function CommonPageProvider({ getService, getPageObjects }) { return await testSubjects.getVisibleText('breadcrumbPageTitle'); } + async getTopNavText() { + return await testSubjects.getVisibleText('top-nav'); + } + async doesCssSelectorExist(selector) { log.debug(`doesCssSelectorExist ${selector}`); @@ -279,6 +302,25 @@ export function CommonPageProvider({ getService, getPageObjects }) { } }); } + + async closeToast() { + const toast = await find.byCssSelector('.euiToast'); + await remote.moveMouseTo(toast); + await find.clickByCssSelector('.euiToast__closeButton'); + } + + async clearAllToasts() { + const toasts = await find.allByCssSelector('.euiToast'); + for (const toastElement of toasts) { + try { + await remote.moveMouseTo(toastElement); + const closeBtn = await toastElement.findByCssSelector('.euiToast__closeButton'); + await closeBtn.click(); + } catch (err) { + // ignore errors, toast clear themselves after timeout + } + } + } } return new CommonPage(); diff --git a/test/functional/page_objects/console_page.js b/test/functional/page_objects/console_page.js index e23b6d407417db..69d73056fbf3be 100644 --- a/test/functional/page_objects/console_page.js +++ b/test/functional/page_objects/console_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Bluebird from 'bluebird'; export function ConsolePageProvider({ getService }) { diff --git a/test/functional/page_objects/context_page.js b/test/functional/page_objects/context_page.js index 675e01c7cb3e56..05caa4c97ad791 100644 --- a/test/functional/page_objects/context_page.js +++ b/test/functional/page_objects/context_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import rison from 'rison-node'; import getUrl from '../../../src/test_utils/get_url'; diff --git a/test/functional/page_objects/dashboard_page.js b/test/functional/page_objects/dashboard_page.js index 70d4f9dd729aa1..9256fb21786c95 100644 --- a/test/functional/page_objects/dashboard_page.js +++ b/test/functional/page_objects/dashboard_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import _ from 'lodash'; import { DashboardConstants } from '../../../src/core_plugins/kibana/public/dashboard/dashboard_constants'; @@ -14,23 +33,28 @@ export function DashboardPageProvider({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'header']); + const dashboardAddPanel = getService('dashboardAddPanel'); + const PageObjects = getPageObjects(['common', 'header', 'settings', 'visualize']); const defaultFindTimeout = config.get('timeouts.find'); class DashboardPage { - async initTests() { + async initTests({ + kibanaIndex = 'dashboard/legacy', + dataIndex = 'logstash_functional', + defaultIndex = 'logstash-*', + } = {}) { log.debug('load kibana index with visualizations and log data'); await Promise.all([ - esArchiver.load('dashboard'), - esArchiver.loadIfNeeded('logstash_functional') + esArchiver.load(kibanaIndex), + esArchiver.loadIfNeeded(dataIndex) ]); await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'UTC', - 'defaultIndex': 'logstash-*' + 'defaultIndex': defaultIndex }); - + await this.selectDefaultIndex(defaultIndex); await kibanaServer.uiSettings.disableToastAutohide(); await PageObjects.common.navigateToApp('dashboard'); } @@ -41,18 +65,11 @@ export function DashboardPageProvider({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); } - async clickEditVisualization() { - log.debug('clickEditVisualization'); - - // Edit link may sometimes be disabled if the embeddable isn't rendered yet. - await retry.try(async () => { - await this.showPanelEditControlsDropdownMenu(); - await testSubjects.click('dashboardPanelEditLink'); - const current = await remote.getCurrentUrl(); - if (current.indexOf('visualize') < 0) { - throw new Error('not on visualize page'); - } - }); + async selectDefaultIndex(indexName) { + await PageObjects.settings.navigateTo(); + await PageObjects.settings.clickKibanaIndices(); + await PageObjects.settings.clickLinkText(indexName); + await PageObjects.settings.clickDefaultIndexButton(); } async clickFullScreenMode() { @@ -127,27 +144,6 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } } - async getQueryInputElement() { - return await testSubjects.find('queryInput'); - } - - async getQuery() { - log.debug(`getQuery`); - const queryInputElement = await this.getQueryInputElement(); - return await queryInputElement.getProperty('value'); - } - - async setQuery(query) { - log.debug(`setQuery(${query})`); - return await testSubjects.setValue('queryInput', query); - } - - async clickFilterButton() { - log.debug('Clicking filter button'); - await testSubjects.click('querySubmitButton'); - await PageObjects.header.waitUntilLoadingHasFinished(); - } - async clickClone() { log.debug('Clicking clone'); await testSubjects.click('dashboardClone'); @@ -171,6 +167,10 @@ export function DashboardPageProvider({ getService, getPageObjects }) { await testSubjects.setValue('clonedDashboardTitle', title); } + async isCloneDuplicateTitleWarningDisplayed() { + return await testSubjects.exists('cloneModalTitleDupicateWarnMsg'); + } + async clickEdit() { log.debug('Clicking edit'); return await testSubjects.click('dashboardEditMode'); @@ -198,22 +198,19 @@ export function DashboardPageProvider({ getService, getPageObjects }) { return await testSubjects.exists('createDashboardPromptButton'); } - async clickListItemCheckbox() { - await testSubjects.click('dashboardListItemCheckbox'); + async checkDashboardListingSelectAllCheckbox() { + const element = await testSubjects.find('checkboxSelectAll'); + const isSelected = await element.isSelected(); + if (!isSelected) { + log.debug(`checking checkbox "checkboxSelectAll"`); + await testSubjects.click('checkboxSelectAll'); + } } async clickDeleteSelectedDashboards() { await testSubjects.click('deleteSelectedDashboards'); } - async clickAddVisualization() { - await testSubjects.click('dashboardAddPanelButton'); - } - - async clickAddNewVisualizationLink() { - await testSubjects.click('addNewSavedObjectLink'); - } - async clickOptions() { await testSubjects.click('dashboardOptionsButton'); } @@ -231,6 +228,14 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } } + // avoids any 'Object with id x not found' errors when switching tests. + async clearSavedObjectsFromAppLinks() { + await PageObjects.header.clickVisualize(); + await PageObjects.visualize.gotoLandingPage(); + await PageObjects.header.clickDashboard(); + await this.gotoDashboardLandingPage(); + } + async isDarkThemeOn() { log.debug('isDarkThemeOn'); await this.openOptions(); @@ -261,48 +266,11 @@ export function DashboardPageProvider({ getService, getPageObjects }) { } } - async clickVizNameLink(vizName) { - await find.clickByPartialLinkText(vizName); - } - - async closeAddVizualizationPanel() { - log.debug('closeAddVizualizationPanel'); - await find.clickByCssSelector('i.fa fa-chevron-up'); - } - async gotoDashboardEditMode(dashboardName) { await this.loadSavedDashboard(dashboardName); await this.clickEdit(); } - async filterEmbeddableNames(name) { - await testSubjects.setValue('savedObjectFinderSearchInput', name); - await PageObjects.header.waitUntilLoadingHasFinished(); - } - - async clickSavedSearchTab() { - await testSubjects.click('addSavedSearchTab'); - } - - async addSavedSearch(searchName) { - await this.clickAddVisualization(); - await this.clickSavedSearchTab(); - await this.filterEmbeddableNames(searchName); - - await find.clickByPartialLinkText(searchName); - await testSubjects.exists('addSavedSearchToDashboardSuccess'); - await this.clickAddVisualization(); - } - - async addVisualization(vizName) { - await this.clickAddVisualization(); - log.debug('filter visualization (' + vizName + ')'); - await this.filterEmbeddableNames(vizName); - await this.clickVizNameLink(vizName); - // this second click of 'Add' collapses the Add Visualization pane - await this.clickAddVisualization(); - } - async renameDashboard(dashName) { log.debug(`Naming dashboard ` + dashName); await testSubjects.click('dashboardRenameButton'); @@ -366,6 +334,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { await retry.try(async () => { const searchFilter = await testSubjects.find('searchFilter'); await searchFilter.clearValue(); + await PageObjects.common.pressEnterKey(); }); } @@ -385,13 +354,14 @@ export function DashboardPageProvider({ getService, getPageObjects }) { await searchFilter.click(); // Note: this replacement of - to space is to preserve original logic but I'm not sure why or if it's needed. await searchFilter.type(dashName.replace('-', ' ')); + await PageObjects.common.pressEnterKey(); }); await PageObjects.header.waitUntilLoadingHasFinished(); } async getCountOfDashboardsInListingTable() { - const dashboardTitles = await testSubjects.findAll('dashboardListingRow'); + const dashboardTitles = await find.allByCssSelector('.dashboardLink'); return dashboardTitles.length; } @@ -431,10 +401,6 @@ export function DashboardPageProvider({ getService, getPageObjects }) { return Promise.all(getTitlePromises); } - async getDashboardPanels() { - return await testSubjects.findAll('dashboardPanel'); - } - async getPanelDimensions() { const panels = await find.allByCssSelector('.react-grid-item'); // These are gridster-defined elements and classes async function getPanelDimensions(panel) { @@ -451,7 +417,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { async getPanelCount() { log.debug('getPanelCount'); - const panels = await find.allByCssSelector('.react-grid-item'); + const panels = await testSubjects.findAll('dashboardPanel'); return panels.length; } @@ -475,39 +441,29 @@ export function DashboardPageProvider({ getService, getPageObjects }) { return this.getTestVisualizations().map(visualization => visualization.description); } - async showPanelEditControlsDropdownMenu() { - log.debug('showPanelEditControlsDropdownMenu'); - const editLinkExists = await testSubjects.exists('dashboardPanelEditLink'); - if (editLinkExists) return; - - await retry.try(async () => { - await testSubjects.click('dashboardPanelToggleMenuIcon'); - const editLinkExists = await testSubjects.exists('dashboardPanelEditLink'); - if (!editLinkExists) { - throw new Error('No edit link exists, toggle menu not open. Try again.'); - } - }); + async getDashboardPanels() { + return await testSubjects.findAll('dashboardPanel'); } - async clickDashboardPanelEditLink() { - await this.showPanelEditControlsDropdownMenu(); - await testSubjects.click('dashboardPanelEditLink'); + async addVisualizations(visualizations) { + await dashboardAddPanel.addVisualizations(visualizations); } - async clickDashboardPanelRemoveIcon() { - await this.showPanelEditControlsDropdownMenu(); - await testSubjects.click('dashboardPanelRemoveIcon'); + async setTimepickerInHistoricalDataRange() { + const fromTime = '2015-09-19 06:31:44.000'; + const toTime = '2015-09-23 18:31:44.000'; + await PageObjects.header.setAbsoluteRange(fromTime, toTime); } - async addVisualizations(visualizations) { - for (const vizName of visualizations) { - await this.addVisualization(vizName); - } + async setTimepickerInDataRange() { + const fromTime = '2018-01-01 00:00:00.000'; + const toTime = '2018-04-13 00:00:00.000'; + await PageObjects.header.setAbsoluteRange(fromTime, toTime); } - async setTimepickerInDataRange() { - const fromTime = '2015-09-19 06:31:44.000'; - const toTime = '2015-09-23 18:31:44.000'; + async setTimepickerInLogstashDataRange() { + const fromTime = '2018-04-09 00:00:00.000'; + const toTime = '2018-04-13 00:00:00.000'; await PageObjects.header.setAbsoluteRange(fromTime, toTime); } @@ -542,70 +498,27 @@ export function DashboardPageProvider({ getService, getPageObjects }) { return _.map(filters, async (filter) => await filter.getVisibleText()); } - async getPieSliceCount() { + async getPieSliceCount(timeout) { log.debug('getPieSliceCount'); return await retry.try(async () => { - const slices = await find.allByCssSelector('svg > g > g.arcs > path.slice'); + const slices = await find.allByCssSelector('svg > g > g.arcs > path.slice', timeout); return slices.length; }); } - async filterOnPieSlice() { - log.debug('Filtering on a pie slice'); - await retry.try(async () => { - const slices = await find.allByCssSelector('svg > g > g.arcs > path.slice'); - log.debug('Slices found:' + slices.length); - return slices[0].click(); - }); - } - - async arePanelMainMenuOptionsOpen(panel) { - log.debug('arePanelMainMenuOptionsOpen'); - // Sub menu used arbitrarily - any option on the main menu panel would do. - return panel ? - await testSubjects.descendantExists('dashboardPanelOptionsSubMenuLink', panel) : - await testSubjects.exists('dashboardPanelOptionsSubMenuLink'); - } - - async openPanelOptions(panel) { - log.debug('openPanelOptions'); - const panelOpen = await this.arePanelMainMenuOptionsOpen(panel); - if (!panelOpen) { + async filterOnPieSlice(sliceValue) { + log.debug(`Filtering on a pie slice with optional value ${sliceValue}`); + if (sliceValue) { + await testSubjects.click(`pieSlice-${sliceValue}`); + } else { await retry.try(async () => { - await (panel ? remote.moveMouseTo(panel) : testSubjects.moveMouseTo('dashboardPanelTitle')); - const toggleMenuItem = panel ? - await testSubjects.findDescendant('dashboardPanelToggleMenuIcon', panel) : - await testSubjects.find('dashboardPanelToggleMenuIcon'); - await toggleMenuItem.click(); - const panelOpen = await this.arePanelMainMenuOptionsOpen(panel); - if (!panelOpen) { throw new Error('Panel menu still not open'); } + const slices = await find.allByCssSelector('svg > g > g.arcs > path.slice'); + log.debug('Slices found:' + slices.length); + return slices[0].click(); }); } } - async toggleExpandPanel(panel) { - await (panel ? remote.moveMouseTo(panel) : testSubjects.moveMouseTo('dashboardPanelTitle')); - const expandShown = await testSubjects.exists('dashboardPanelExpandIcon'); - if (!expandShown) { - await this.openPanelOptions(panel); - } - await testSubjects.click('dashboardPanelExpandIcon'); - } - - async setCustomPanelTitle(customTitle, panel) { - log.debug(`setCustomPanelTitle(${customTitle}, ${panel})`); - await this.openPanelOptions(panel); - await testSubjects.click('dashboardPanelOptionsSubMenuLink'); - await testSubjects.setValue('customDashboardPanelTitleInput', customTitle); - } - - async resetCustomPanelTitle(panel) { - log.debug('resetCustomPanelTitle'); - await this.openPanelOptions(panel); - await testSubjects.click('dashboardPanelOptionsSubMenuLink'); - await testSubjects.click('resetCustomDashboardPanelTitle'); - } - async getSharedItemsCount() { log.debug('in getSharedItemsCount'); const attributeName = 'data-shared-items-count'; @@ -624,15 +537,27 @@ export function DashboardPageProvider({ getService, getPageObjects }) { return await sharedItem.getAttribute('data-render-complete'); })); if (renderComplete.length !== sharedItems.length) { - throw new Error('Some shared items dont have data-render-complete attribute'); + const expecting = `expecting: ${sharedItems.length}, received: ${renderComplete.length}`; + throw new Error( + `Some shared items dont have data-render-complete attribute, ${expecting}`); } const totalCount = renderComplete.filter(value => value === 'true' || value === 'disabled').length; if (totalCount < sharedItems.length) { - throw new Error('Still waiting on more visualizations to finish rendering'); + const expecting = `${sharedItems.length}, received: ${totalCount}`; + throw new Error(`Still waiting on more visualizations to finish rendering, expecting: ${expecting}`); } }); } + async getSharedContainerData() { + log.debug('getSharedContainerData'); + const sharedContainer = await find.byCssSelector('[data-shared-items-container]'); + return { + title: await sharedContainer.getAttribute('data-title'), + description: await sharedContainer.getAttribute('data-description') + }; + } + async getPanelSharedItemData() { log.debug('in getPanelSharedItemData'); const sharedItems = await find.allByCssSelector('[data-shared-item]'); diff --git a/test/functional/page_objects/discover_page.js b/test/functional/page_objects/discover_page.js index 6c76ea59f6e040..cd85e17d89bd27 100644 --- a/test/functional/page_objects/discover_page.js +++ b/test/functional/page_objects/discover_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function DiscoverPageProvider({ getService, getPageObjects }) { const config = getService('config'); const log = getService('log'); @@ -55,7 +74,12 @@ export function DiscoverPageProvider({ getService, getPageObjects }) { async openSavedSearch() { await this.clickLoadSavedSearchButton(); - await testSubjects.exists('loadSearchForm'); + await retry.try(async () => { + const isLoadFormVisible = await testSubjects.exists('loadSearchForm'); + if (!isLoadFormVisible) { + throw new Error('Load search form not visible yet.'); + } + }); } async hasSavedSearch(searchName) { diff --git a/test/functional/page_objects/header_page.js b/test/functional/page_objects/header_page.js index 0effdcb57598c6..1003121aa364d5 100644 --- a/test/functional/page_objects/header_page.js +++ b/test/functional/page_objects/header_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function HeaderPageProvider({ getService, getPageObjects }) { const config = getService('config'); const remote = getService('remote'); @@ -13,34 +32,45 @@ export function HeaderPageProvider({ getService, getPageObjects }) { async clickSelector(selector) { log.debug(`clickSelector(${selector})`); - await retry.try(async () => await remote.findByCssSelector(selector).click()); + await find.clickByCssSelector(selector); + } + + async confirmTopNavTextContains(text) { + await retry.try(async () => { + const topNavText = await PageObjects.common.getTopNavText(); + if (topNavText.toLowerCase().indexOf(text.toLowerCase()) < 0) { + throw new Error(`Top nav text ${topNavText} does not contain ${text} (case insensitive)`); + } + }); } async clickDiscover() { log.debug('click Discover tab'); await this.clickSelector('a[href*=\'discover\']'); await PageObjects.common.waitForTopNavToBeVisible(); - await this.isGlobalLoadingIndicatorHidden(); + await this.awaitGlobalLoadingIndicatorHidden(); } async clickVisualize() { log.debug('click Visualize tab'); await this.clickSelector('a[href*=\'visualize\']'); await PageObjects.common.waitForTopNavToBeVisible(); - await this.isGlobalLoadingIndicatorHidden(); + await this.confirmTopNavTextContains('visualize'); + await this.awaitGlobalLoadingIndicatorHidden(); } async clickDashboard() { log.debug('click Dashboard tab'); await this.clickSelector('a[href*=\'dashboard\']'); await PageObjects.common.waitForTopNavToBeVisible(); - await this.isGlobalLoadingIndicatorHidden(); + await this.confirmTopNavTextContains('dashboard'); + await this.awaitGlobalLoadingIndicatorHidden(); } async clickManagement() { log.debug('click Management tab'); await this.clickSelector('a[href*=\'management\']'); - await this.isGlobalLoadingIndicatorHidden(); + await this.awaitGlobalLoadingIndicatorHidden(); } async clickSettings() { @@ -158,7 +188,7 @@ export function HeaderPageProvider({ getService, getPageObjects }) { log.debug('--Setting To Time : ' + toTime); await this.setToTime(toTime); await this.clickGoButton(); - await this.isGlobalLoadingIndicatorHidden(); + await this.awaitGlobalLoadingIndicatorHidden(); } async setQuickTime(quickTime) { @@ -225,7 +255,7 @@ export function HeaderPageProvider({ getService, getPageObjects }) { throw exception; } } - await this.isGlobalLoadingIndicatorHidden(); + await this.awaitGlobalLoadingIndicatorHidden(); } async isGlobalLoadingIndicatorVisible() { @@ -233,9 +263,9 @@ export function HeaderPageProvider({ getService, getPageObjects }) { return await testSubjects.exists('globalLoadingIndicator'); } - async isGlobalLoadingIndicatorHidden() { - log.debug('isGlobalLoadingIndicatorHidden'); - return await find.byCssSelector('[data-test-subj="globalLoadingIndicator"].ng-hide', defaultFindTimeout * 10); + async awaitGlobalLoadingIndicatorHidden() { + log.debug('awaitGlobalLoadingIndicatorHidden'); + await testSubjects.find('globalLoadingIndicator-hidden', defaultFindTimeout * 10); } async getPrettyDuration() { diff --git a/test/functional/page_objects/home_page.js b/test/functional/page_objects/home_page.js index 8c50816498b3af..3acb03080bd8c9 100644 --- a/test/functional/page_objects/home_page.js +++ b/test/functional/page_objects/home_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function HomePageProvider({ getService }) { const testSubjects = getService('testSubjects'); @@ -16,6 +35,34 @@ export function HomePageProvider({ getService }) { return await testSubjects.exists(`homeSynopsisLink${title}`); } + async doesSampleDataSetExist(id) { + return await testSubjects.exists(`sampleDataSetCard${id}`); + } + + async doesSampleDataSetSuccessfulInstallToastExist() { + return await testSubjects.exists('sampleDataSetInstallToast'); + } + + async doesSampleDataSetSuccessfulUninstallToastExist() { + return await testSubjects.exists('sampleDataSetUninstallToast'); + } + + async isSampleDataSetInstalled(id) { + return await testSubjects.exists(`removeSampleDataSet${id}`); + } + + async addSampleDataSet(id) { + await testSubjects.click(`addSampleDataSet${id}`); + } + + async removeSampleDataSet(id) { + await testSubjects.click(`removeSampleDataSet${id}`); + } + + async launchSampleDataSet(id) { + await testSubjects.click(`launchSampleDataSet${id}`); + } + } return new HomePage(); diff --git a/test/functional/page_objects/index.js b/test/functional/page_objects/index.js index eff68acc8e505c..72f07453041d1a 100644 --- a/test/functional/page_objects/index.js +++ b/test/functional/page_objects/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { ConsolePageProvider } from './console_page'; export { CommonPageProvider } from './common_page'; export { ShieldPageProvider } from './shield_page'; diff --git a/test/functional/page_objects/monitoring_page.js b/test/functional/page_objects/monitoring_page.js index 479ccef91faf95..5935044a037ae0 100644 --- a/test/functional/page_objects/monitoring_page.js +++ b/test/functional/page_objects/monitoring_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function MonitoringPageProvider({ getService }) { const testSubjects = getService('testSubjects'); diff --git a/test/functional/page_objects/point_series_page.js b/test/functional/page_objects/point_series_page.js index 3d0fb5cc496db3..70bc3de97c7d28 100644 --- a/test/functional/page_objects/point_series_page.js +++ b/test/functional/page_objects/point_series_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function PointSeriesPageProvider({ getService }) { const remote = getService('remote'); const config = getService('config'); diff --git a/test/functional/page_objects/settings_page.js b/test/functional/page_objects/settings_page.js index 91ec48f84bcfb9..9f3c54c1be5664 100644 --- a/test/functional/page_objects/settings_page.js +++ b/test/functional/page_objects/settings_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { map as mapAsync } from 'bluebird'; export function SettingsPageProvider({ getService, getPageObjects }) { @@ -38,42 +57,42 @@ export function SettingsPageProvider({ getService, getPageObjects }) { async getAdvancedSettings(propertyName) { log.debug('in getAdvancedSettings'); - return await testSubjects.getVisibleText(`advancedSetting-${propertyName}-currentValue`); + const setting = await testSubjects.find(`advancedSetting-editField-${propertyName}`); + return await setting.getProperty('value'); + } + + async getAdvancedSettingCheckbox(propertyName) { + log.debug('in getAdvancedSettingCheckbox'); + const setting = await testSubjects.find(`advancedSetting-editField-${propertyName}`); + return await setting.getProperty('checked'); } async clearAdvancedSettings(propertyName) { - await testSubjects.click(`advancedSetting-${propertyName}-clearButton`); + await testSubjects.click(`advancedSetting-resetField-${propertyName}`); await PageObjects.header.waitUntilLoadingHasFinished(); } async setAdvancedSettingsSelect(propertyName, propertyValue) { - await testSubjects.click(`advancedSetting-${propertyName}-editButton`); - await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.common.sleep(1000); await remote.setFindTimeout(defaultFindTimeout) - .findByCssSelector(`option[label="${propertyValue}"]`).click(); + .findByCssSelector(`[data-test-subj="advancedSetting-editField-${propertyName}"] option[value="${propertyValue}"]`).click(); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.click(`advancedSetting-${propertyName}-saveButton`); + await testSubjects.click(`advancedSetting-saveEditField-${propertyName}`); await PageObjects.header.waitUntilLoadingHasFinished(); } - async setAdvancedSettingsInput(propertyName, propertyValue, inputSelector) { - await testSubjects.click(`advancedSetting-${propertyName}-editButton`); - await PageObjects.header.waitUntilLoadingHasFinished(); - const input = await testSubjects.find(inputSelector); + async setAdvancedSettingsInput(propertyName, propertyValue) { + const input = await testSubjects.find(`advancedSetting-editField-${propertyName}`); await input.clearValue(); await input.type(propertyValue); - await testSubjects.click(`advancedSetting-${propertyName}-saveButton`); + await testSubjects.click(`advancedSetting-saveEditField-${propertyName}`); await PageObjects.header.waitUntilLoadingHasFinished(); } async toggleAdvancedSettingCheckbox(propertyName) { - await testSubjects.click(`advancedSetting-${propertyName}-editButton`); - await PageObjects.header.waitUntilLoadingHasFinished(); - const checkbox = await testSubjects.find(`advancedSetting-${propertyName}-checkbox`); + const checkbox = await testSubjects.find(`advancedSetting-editField-${propertyName}`); await checkbox.click(); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.click(`advancedSetting-${propertyName}-saveButton`); + await testSubjects.click(`advancedSetting-saveEditField-${propertyName}`); await PageObjects.header.waitUntilLoadingHasFinished(); } @@ -189,12 +208,6 @@ export function SettingsPageProvider({ getService, getPageObjects }) { }); } - getPageSize() { - return remote.setFindTimeout(defaultFindTimeout) - .findByCssSelector('div.euiPopover button.euiButtonEmpty span.euiButtonEmpty__content span') - .getVisibleText(); - } - async getFieldNames() { const fieldNameCells = await testSubjects.findAll('editIndexPattern indexedFieldName'); return await mapAsync(fieldNameCells, async cell => { @@ -228,18 +241,6 @@ export function SettingsPageProvider({ getService, getPageObjects }) { .click(); } - async goToPage(pageNum) { - const pageButtons = await remote.setFindTimeout(defaultFindTimeout) - .findAllByCssSelector('.euiPagination button.euiPaginationButton') - .getVisibleText(); - - await remote.setFindTimeout(defaultFindTimeout) - .findByCssSelector(`.euiPagination button.euiPaginationButton:nth-child(${pageButtons.indexOf(pageNum + '') + 2})`) - .click(); - - await PageObjects.header.waitUntilLoadingHasFinished(); - } - async filterField(name) { const input = await testSubjects.find('indexPatternFieldFilter'); await input.clearValue(); @@ -247,6 +248,7 @@ export function SettingsPageProvider({ getService, getPageObjects }) { } async openControlsByName(name) { + await this.filterField(name); const tableFields = await remote.setFindTimeout(defaultFindTimeout) .findAllByCssSelector('table.euiTable tbody tr.euiTableRow td.euiTableRowCell:first-child') .getVisibleText(); @@ -278,29 +280,6 @@ export function SettingsPageProvider({ getService, getPageObjects }) { await PageObjects.header.waitUntilLoadingHasFinished(); } - async setPageSize(size) { - try { - await remote.setFindTimeout(defaultFindTimeout) - .findByCssSelector('div.euiPopover button.euiButtonEmpty') - .click(); - - const sizeButtons = await remote.setFindTimeout(defaultFindTimeout) - .findAllByCssSelector('div.euiPopover .euiContextMenuPanel button.euiContextMenuItem') - .getVisibleText(); - - await remote.setFindTimeout(defaultFindTimeout) - .findAllByCssSelector(`div.euiPopover .euiContextMenuPanel - button.euiContextMenuItem:nth-child(${sizeButtons.indexOf(size + ' rows') + 1})`) - .click(); - } catch(e) { - await remote.setFindTimeout(defaultFindTimeout) - .findByCssSelector(`[data-test-subj="paginateControlsPageSizeSelect"] option[label="${size}"]`) - .click(); - } finally { - await PageObjects.header.waitUntilLoadingHasFinished(); - } - } - async createIndexPattern(indexPatternName, timefield = '@timestamp') { await retry.try(async () => { await this.navigateTo(); @@ -519,32 +498,73 @@ export function SettingsPageProvider({ getService, getPageObjects }) { await testSubjects.setValue('editorFieldScript', script); } - async importFile(path) { + async importFile(path, overwriteAll = true) { log.debug(`importFile(${path})`); - await remote.findById('testfile').type(path); + + log.debug(`Clicking importObjects`); + await testSubjects.click('importObjects'); + log.debug(`Setting the path on the file input`); + await find.setValue('.euiFilePicker__input', path); + if (!overwriteAll) { + log.debug(`Toggling overwriteAll`); + await testSubjects.click('importSavedObjectsOverwriteToggle'); + } else { + log.debug(`Leaving overwriteAll alone`); + } + await testSubjects.click('importSavedObjectsImportBtn'); + log.debug(`done importing the file`); + } + + async clickImportDone() { + await testSubjects.click('importSavedObjectsDoneBtn'); + } + + async clickConfirmConflicts() { + await testSubjects.click('importSavedObjectsConfirmBtn'); } async setImportIndexFieldOption(child) { - await remote.setFindTimeout(defaultFindTimeout) - .findByCssSelector(`select[data-test-subj="managementChangeIndexSelection"] > option:nth-child(${child})`) - .click(); + await find + .clickByCssSelector(`select[data-test-subj="managementChangeIndexSelection"] > option:nth-child(${child})`); } async clickChangeIndexConfirmButton() { - await (await testSubjects.find('changeIndexConfirmButton')).click(); + await testSubjects.click('changeIndexConfirmButton'); } async clickVisualizationsTab() { - await (await testSubjects.find('objectsTab-visualizations')).click(); + await testSubjects.click('objectsTab-visualizations'); } async clickSearchesTab() { - await (await testSubjects.find('objectsTab-searches')).click(); + await testSubjects.click('objectsTab-searches'); } async getVisualizationRows() { return await testSubjects.findAll(`objectsTableRow`); } + + async waitUntilSavedObjectsTableIsNotLoading() { + return retry.try(async () => { + const exists = await find.existsByDisplayedByCssSelector('*[data-test-subj="savedObjectsTable"] .euiBasicTable-loading'); + if (exists) { + throw new Error('Waiting'); + } + return true; + }); + } + + async getSavedObjectsInTable() { + const table = await testSubjects.find('savedObjectsTable'); + const cells = await table.findAll('css selector', 'td:nth-child(3)'); + + const objects = []; + for (const cell of cells) { + objects.push(await cell.getVisibleText()); + } + + return objects; + } } return new SettingsPage(); diff --git a/test/functional/page_objects/shield_page.js b/test/functional/page_objects/shield_page.js index ed4b14e4e194c9..ec822f62e0fdf6 100644 --- a/test/functional/page_objects/shield_page.js +++ b/test/functional/page_objects/shield_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function ShieldPageProvider({ getService }) { const remote = getService('remote'); const config = getService('config'); diff --git a/test/functional/page_objects/timelion_page.js b/test/functional/page_objects/timelion_page.js index 93dfc91c5550d7..0532596137f0dc 100644 --- a/test/functional/page_objects/timelion_page.js +++ b/test/functional/page_objects/timelion_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function TimelionPageProvider({ getService, getPageObjects }) { const testSubjects = getService('testSubjects'); const find = getService('find'); diff --git a/test/functional/page_objects/visual_builder_page.js b/test/functional/page_objects/visual_builder_page.js index 37f4e641eec92a..42cd0d2f5cb92a 100644 --- a/test/functional/page_objects/visual_builder_page.js +++ b/test/functional/page_objects/visual_builder_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import Keys from 'leadfoot/keys'; export function VisualBuilderPageProvider({ getService, getPageObjects }) { @@ -5,7 +24,7 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }) { const retry = getService('retry'); const log = getService('log'); const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'header']); + const PageObjects = getPageObjects(['common', 'header', 'visualize']); class VisualBuilderPage { @@ -133,12 +152,9 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }) { }); } - async selectAggType(type, nth = 0) { + async selectAggType(value, nth = 0) { const elements = await testSubjects.findAll('aggSelector'); - const input = await elements[nth].findByCssSelector('.Select-input input'); - await input.type(type); - const option = await elements[nth].findByCssSelector('.Select-option'); - await option.click(); + await PageObjects.visualize.setComboBoxElement(elements[nth], value); return await PageObjects.header.waitUntilLoadingHasFinished(); } @@ -150,22 +166,17 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }) { async fillInVariable(name = 'test', metric = 'count', nth = 0) { const elements = await testSubjects.findAll('varRow'); - const input = await elements[nth].findByCssSelector('.vis_editor__calc_vars-name input'); - await input.type(name); - const select = await elements[nth].findByCssSelector('.Select-input input'); - await select.type(metric); - const option = await elements[nth].findByCssSelector('.Select-option'); - await option.click(); + const varNameInput = await elements[nth].findByCssSelector('.vis_editor__calc_vars-name input'); + await varNameInput.type(name); + const metricSelectWrapper = await elements[nth].findByCssSelector('.vis_editor__calc_vars-var'); + await PageObjects.visualize.setComboBoxElement(metricSelectWrapper, metric); return await PageObjects.header.waitUntilLoadingHasFinished(); } async selectGroupByField(fieldName) { const element = await testSubjects.find('groupByField'); - const input = await element.findByCssSelector('.Select-input input'); - await input.type(fieldName); - const option = await element.findByCssSelector('.Select-option'); - await option.click(); + await PageObjects.visualize.setComboBoxElement(element, fieldName); } async setLabelValue(value) { diff --git a/test/functional/page_objects/visualize_page.js b/test/functional/page_objects/visualize_page.js index bad478af7d6193..679096c88b47ba 100644 --- a/test/functional/page_objects/visualize_page.js +++ b/test/functional/page_objects/visualize_page.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { VisualizeConstants } from '../../../src/core_plugins/kibana/public/visualize/visualize_constants'; import Keys from 'leadfoot/keys'; import Bluebird from 'bluebird'; @@ -42,6 +61,10 @@ export function VisualizePageProvider({ getService, getPageObjects }) { await find.clickByCssSelector('[group-name="metrics"] [data-test-subj="visualizeEditorAddAggregationButton"]'); } + async clickAddBucket() { + await find.clickByCssSelector('[group-name="buckets"] [data-test-subj="visualizeEditorAddAggregationButton"]'); + } + async clickMetric() { await find.clickByPartialLinkText('Metric'); } @@ -194,41 +217,60 @@ export function VisualizePageProvider({ getService, getPageObjects }) { await input.type(timeString); } - async setReactSelect(className, value) { - const input = await find.byCssSelector(className + ' * input', 0); - await input.clearValue(); - await input.type(value); - await find.clickByCssSelector('.Select-option'); - const stillOpen = await find.existsByCssSelector('.Select-menu-outer', 0); - if (stillOpen) { - await find.clickByCssSelector(className + ' * .Select-arrow-zone'); - } + async setComboBox(comboBoxSelector, value) { + const comboBox = await testSubjects.find(comboBoxSelector); + await this.setComboBoxElement(comboBox, value); } - async clearReactSelect(className) { - await find.clickByCssSelector(className + ' * .Select-clear-zone'); + async setComboBoxElement(element, value) { + const input = await element.findByTagName('input'); + await input.clearValue(); + await input.type(value); + await find.clickByCssSelector('.euiComboBoxOption'); + await this.closeComboBoxOptionsList(element); } - async getReactSelectOptions(containerSelector) { - await testSubjects.click(containerSelector); + async getComboBoxOptions(comboBoxSelector) { + await testSubjects.click(comboBoxSelector); const menu = await retry.try( - async () => find.byCssSelector('.Select-menu-outer')); - return await menu.getVisibleText(); + async () => await testSubjects.find('comboBoxOptionsList')); + const optionsText = await menu.getVisibleText(); + const comboBox = await testSubjects.find(comboBoxSelector); + await this.closeComboBoxOptionsList(comboBox); + return optionsText; } - async doesReactSelectHaveValue(className) { - return await find.existsByCssSelector(className + ' * .Select-value-label', 0); + async doesComboBoxHaveSelectedOptions(comboBoxSelector) { + const comboBox = await testSubjects.find(comboBoxSelector); + const selectedOptions = await comboBox.findAllByClassName('euiComboBoxPill'); + return selectedOptions > 0; } - async getReactSelectValue(className) { - const hasValue = await this.doesReactSelectHaveValue(className); - if (!hasValue) { - return ''; + async getComboBoxSelectedOptions(comboBoxSelector) { + const comboBox = await testSubjects.find(comboBoxSelector); + const selectedOptions = await comboBox.findAllByClassName('euiComboBoxPill'); + if (selectedOptions.length === 0) { + return []; } - const valueElement = await retry.try( - async () => find.byCssSelector(className + ' * .Select-value-label')); - return await valueElement.getVisibleText(); + const getOptionValuePromises = selectedOptions.map(async (optionElement) => { + return await optionElement.getVisibleText(); + }); + return await Promise.all(getOptionValuePromises); + } + + async clearComboBox(comboBoxSelector) { + const comboBox = await testSubjects.find(comboBoxSelector); + const clearBtn = await comboBox.findByCssSelector('button.euiFormControlLayout__clear'); + await clearBtn.click(); + } + + async closeComboBoxOptionsList(comboBoxElement) { + const isOptionsListOpen = await testSubjects.exists('comboBoxOptionsList'); + if (isOptionsListOpen) { + const closeBtn = await comboBoxElement.findByCssSelector('button.euiFormControlLayout__icon'); + await closeBtn.click(); + } } async addInputControl() { @@ -375,12 +417,12 @@ export function VisualizePageProvider({ getService, getPageObjects }) { }); } - async toggleOpenEditor(index) { + async toggleOpenEditor(index, toState = 'true') { // index, see selectYAxisAggregation const toggle = await find.byCssSelector(`button[aria-controls="visAggEditorParams${index}"]`); const toggleOpen = await toggle.getAttribute('aria-expanded'); log.debug(`toggle ${index} expand = ${toggleOpen}`); - if (toggleOpen === 'false') { + if (toggleOpen !== toState) { log.debug(`toggle ${index} click()`); await toggle.click(); } @@ -500,6 +542,10 @@ export function VisualizePageProvider({ getService, getPageObjects }) { await input.type(newValue); } + async toggleDisabledAgg(agg) { + await testSubjects.click(`aggregationEditor${agg} disableAggregationBtn`); + } + async toggleOtherBucket() { return await find.clickByCssSelector('input[name="showOther"]'); } @@ -558,11 +604,14 @@ export function VisualizePageProvider({ getService, getPageObjects }) { }); } - async saveVisualization(vizName) { + async saveVisualization(vizName, { saveAsNew = false } = {}) { await this.ensureSavePanelOpen(); await testSubjects.setValue('visTitleInput', vizName); log.debug('click submit button'); await testSubjects.click('saveVisualizationButton'); + if (saveAsNew) { + await testSubjects.click('saveAsNewCheckbox'); + } await PageObjects.header.waitUntilLoadingHasFinished(); return await testSubjects.exists('saveVisualizationSuccess'); } @@ -753,9 +802,13 @@ export function VisualizePageProvider({ getService, getPageObjects }) { return await dataTable.getVisibleText(); } - async getDataTableHeaders() { + async getDataTableHeaders(parent) { const dataTableHeader = await retry.try( - async () => testSubjects.find('paginated-table-header')); + async () => ( + parent ? + testSubjects.findDescendant('paginated-table-header', parent) : + testSubjects.find('paginated-table-header') + )); return await dataTableHeader.getVisibleText(); } @@ -873,8 +926,26 @@ export function VisualizePageProvider({ getService, getPageObjects }) { } } - async clickLegendOption(name) { - await testSubjects.click(`legend-${name}`); + async getLegendEntries() { + const legendEntries = await find.allByCssSelector('.legend-value-title', defaultFindTimeout * 2); + return await Promise.all(legendEntries.map(async chart => await chart.getAttribute('data-label'))); + } + + async openLegendOptionColors(name) { + await retry.try(async () => { + // This click has been flaky in opening the legend, hence the retry. See + // https://github.com/elastic/kibana/issues/17468 + await testSubjects.click(`legend-${name}`); + // arbitrary color chosen, any available would do + const isOpen = await this.doesLegendColorChoiceExist('#EF843C'); + if (!isOpen) { + throw new Error('legend color selector not open'); + } + }); + } + + async doesLegendColorChoiceExist(color) { + return await testSubjects.exists(`legendSelectColor-${color}`); } async selectNewLegendColorChoice(color) { diff --git a/test/functional/screenshots/baseline/area_chart.png b/test/functional/screenshots/baseline/area_chart.png index 13376e741815d4..75240f4db51790 100644 Binary files a/test/functional/screenshots/baseline/area_chart.png and b/test/functional/screenshots/baseline/area_chart.png differ diff --git a/test/functional/screenshots/baseline/tsvb_dashboard.png b/test/functional/screenshots/baseline/tsvb_dashboard.png index dbe4c828e09415..42365fa8a850b7 100644 Binary files a/test/functional/screenshots/baseline/tsvb_dashboard.png and b/test/functional/screenshots/baseline/tsvb_dashboard.png differ diff --git a/test/functional/services/dashboard/add_panel.js b/test/functional/services/dashboard/add_panel.js new file mode 100644 index 00000000000000..1277e5fad2a1e5 --- /dev/null +++ b/test/functional/services/dashboard/add_panel.js @@ -0,0 +1,183 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +export function DashboardAddPanelProvider({ getService, getPageObjects }) { + const log = getService('log'); + const retry = getService('retry'); + const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects(['header', 'common']); + + return new class DashboardAddPanel { + async clickOpenAddPanel() { + log.debug('DashboardAddPanel.clickOpenAddPanel'); + await testSubjects.click('dashboardAddPanelButton'); + } + + async clickAddNewEmbeddableLink() { + await testSubjects.click('addNewSavedObjectLink'); + } + + async clickSavedSearchTab() { + await testSubjects.click('addSavedSearchTab'); + } + + async addEveryEmbeddableOnCurrentPage() { + log.debug('addEveryEmbeddableOnCurrentPage'); + const addPanel = await testSubjects.find('dashboardAddPanel'); + const embeddableRows = await addPanel.findAllByClassName('euiLink'); + for (let i = 0; i < embeddableRows.length; i++) { + await embeddableRows[i].click(); + } + log.debug(`Added ${embeddableRows.length} embeddables`); + } + + async clickPagerNextButton() { + // Clear all toasts that could hide pagination controls + await PageObjects.common.clearAllToasts(); + + const addPanel = await testSubjects.find('dashboardAddPanel'); + const pagination = await addPanel.findAllByClassName('euiPagination'); + if (pagination.length === 0) { + return false; + } + + const pagerNextButton = await pagination[0].findByCssSelector('button[aria-label="Next page"]'); + if (!pagerNextButton) { + return false; + } + + const isDisabled = await pagerNextButton.getAttribute('disabled'); + if (isDisabled != null) { + return false; + } + + await pagerNextButton.click(); + await PageObjects.header.waitUntilLoadingHasFinished(); + return true; + } + + async isAddPanelOpen() { + log.debug('DashboardAddPanel.isAddPanelOpen'); + return await testSubjects.exists('dashboardAddPanel'); + } + + async ensureAddPanelIsShowing() { + log.debug('DashboardAddPanel.ensureAddPanelIsShowing'); + const isOpen = await this.isAddPanelOpen(); + if (!isOpen) { + await retry.try(async () => { + await this.clickOpenAddPanel(); + const isOpen = await this.isAddPanelOpen(); + if (!isOpen) { + throw new Error('Add panel still not open, trying again.'); + } + }); + } + } + + async closeAddPanel() { + log.debug('closeAddPanel'); + const isOpen = await this.isAddPanelOpen(); + if (isOpen) { + await retry.try(async () => { + await testSubjects.click('closeAddPanelBtn'); + const isOpen = await this.isAddPanelOpen(); + if (isOpen) { + throw new Error('Add panel still open, trying again.'); + } + }); + } + } + + async addEveryVisualization(filter) { + log.debug('DashboardAddPanel.addEveryVisualization'); + await this.ensureAddPanelIsShowing(); + if (filter) { + await this.filterEmbeddableNames(filter.replace('-', ' ')); + } + let morePages = true; + while (morePages) { + await this.addEveryEmbeddableOnCurrentPage(); + morePages = await this.clickPagerNextButton(); + } + await this.closeAddPanel(); + } + + async addEverySavedSearch(filter) { + log.debug('DashboardAddPanel.addEverySavedSearch'); + await this.ensureAddPanelIsShowing(); + await this.clickSavedSearchTab(); + if (filter) { + await this.filterEmbeddableNames(filter.replace('-', ' ')); + } + let morePages = true; + while (morePages) { + await this.addEveryEmbeddableOnCurrentPage(); + morePages = await this.clickPagerNextButton(); + } + await this.closeAddPanel(); + } + + async addSavedSearch(searchName) { + log.debug(`addSavedSearch(${searchName})`); + + await this.ensureAddPanelIsShowing(); + await this.clickSavedSearchTab(); + await this.filterEmbeddableNames(searchName); + + await testSubjects.click(`addPanel${searchName.split(' ').join('-')}`); + await testSubjects.exists('addSavedSearchToDashboardSuccess'); + await this.closeAddPanel(); + } + + async addSavedSearches(searches) { + for (const name of searches) { + await this.addSavedSearch(name); + } + } + + async addVisualizations(visualizations) { + log.debug('DashboardAddPanel.addVisualizations'); + for (const vizName of visualizations) { + await this.addVisualization(vizName); + } + } + + async addVisualization(vizName) { + log.debug(`DashboardAddPanel.addVisualization(${vizName})`); + await this.ensureAddPanelIsShowing(); + await this.filterEmbeddableNames(`"${vizName.replace('-', ' ')}"`); + await testSubjects.click(`addPanel${vizName.split(' ').join('-')}`); + await this.closeAddPanel(); + } + + async filterEmbeddableNames(name) { + await testSubjects.setValue('savedObjectFinderSearchInput', name); + await PageObjects.header.waitUntilLoadingHasFinished(); + } + + async panelAddLinkExists(name) { + log.debug(`DashboardAddPanel.panelAddLinkExists(${name})`); + await this.ensureAddPanelIsShowing(); + await this.filterEmbeddableNames(`"${name}"`); + return await testSubjects.exists(`addPanel${name.split(' ').join('-')}`); + } + }; +} diff --git a/test/functional/services/dashboard/expectations.js b/test/functional/services/dashboard/expectations.js index ca8c5fa56237e0..f0e43bc8526d4d 100644 --- a/test/functional/services/dashboard/expectations.js +++ b/test/functional/services/dashboard/expectations.js @@ -1,11 +1,31 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import expect from 'expect.js'; export function DashboardExpectProvider({ getService, getPageObjects }) { const log = getService('log'); const retry = getService('retry'); const testSubjects = getService('testSubjects'); + const find = getService('find'); const filterBar = getService('filterBar'); - const PageObjects = getPageObjects(['dashboard']); + const PageObjects = getPageObjects(['dashboard', 'visualize']); return new class DashboardExpect { async pieSliceCount(expectedCount) { @@ -35,8 +55,15 @@ export function DashboardExpectProvider({ getService, getPageObjects }) { async docTableFieldCount(expectedCount) { log.debug(`DashboardExpect.docTableFieldCount(${expectedCount})`); await retry.try(async () => { - const docTableCellCounts = await testSubjects.findAll(`docTableField`); - expect(docTableCellCounts.length).to.be(expectedCount); + const docTableCells = await testSubjects.findAll('docTableField'); + expect(docTableCells.length).to.be(expectedCount); + }); + } + + async tsvbTimeSeriesLegendCount(expectedCount) { + await retry.try(async () => { + const tsvbLegendItems = await testSubjects.findAll('tsvbLegendItem'); + expect(tsvbLegendItems.length).to.be(expectedCount); }); } @@ -44,5 +71,164 @@ export function DashboardExpectProvider({ getService, getPageObjects }) { const indexPatterns = await filterBar.getFilterFieldIndexPatterns(); expect(indexPatterns).to.eql(expectedIndexPatterns); } + + async legendValuesToExist(legendValues) { + await Promise.all(legendValues.map(async legend => { + await retry.try(async () => { + const legendValueExists = await testSubjects.exists(`legend-${legend}`); + expect(legendValueExists).to.be(true); + }); + })); + } + + async textWithinElementsExists(texts, getElementsFn) { + await retry.try(async () => { + const elements = await getElementsFn(); + const elementTexts = []; + await Promise.all(elements.map(async element => { + elementTexts.push(await element.getVisibleText()); + })); + log.debug(`Found ${elements.length} elements with values: ${JSON.stringify(elementTexts)}`); + texts.forEach(value => { + const indexOfValue = elementTexts.indexOf(value); + expect(indexOfValue).to.be.greaterThan(-1); + elementTexts.splice(indexOfValue, 1); + }); + }); + } + + async textWithinTestSubjectsExists(texts, selector) { + log.debug(`textWithinTestSubjectsExists:(${JSON.stringify(texts)},${selector})`); + await this.textWithinElementsExists(texts, async () => await testSubjects.findAll(selector)); + } + + async textWithinCssElementExists(texts, selector) { + log.debug(`textWithinCssElementExists:(${JSON.stringify(texts)},${selector})`); + await this.textWithinElementsExists(texts, async () => await find.allByCssSelector(selector)); + } + + async textWithinElementsDoNotExist(texts, getElementsFn) { + await retry.try(async () => { + const elements = await getElementsFn(); + const elementTexts = []; + await Promise.all(elements.map(async element => { + elementTexts.push(await element.getVisibleText()); + })); + log.debug(`Found ${elements.length} elements with values: ${JSON.stringify(elementTexts)}`); + texts.forEach(value => { + const indexOfValue = elementTexts.indexOf(value); + expect(indexOfValue).to.be(-1); + }); + }); + } + + async textWithinCssElementDoNotExist(texts, selector) { + log.debug(`textWithinCssElementExists:(${JSON.stringify(texts)},${selector})`); + await this.textWithinElementsDoNotExist(texts, async () => await find.allByCssSelector(selector)); + } + + async timelionLegendCount(expectedCount) { + await retry.try(async () => { + const flotLegendLabels = await testSubjects.findAll('flotLegendLabel'); + expect(flotLegendLabels.length).to.be(expectedCount); + }); + } + + async emptyTagCloudFound() { + const tagCloudVisualizations = await testSubjects.findAll('tagCloudVisualization'); + const tagCloudsHaveContent = await Promise.all(tagCloudVisualizations.map(async tagCloud => { + return await find.descendantExistsByCssSelector('text', tagCloud); + })); + expect(tagCloudsHaveContent.indexOf(false)).to.be.greaterThan(-1); + } + + async tagCloudWithValuesFound(values) { + const tagCloudVisualizations = await testSubjects.findAll('tagCloudVisualization'); + const matches = await Promise.all(tagCloudVisualizations.map(async tagCloud => { + for (let i = 0; i < values.length; i++) { + const valueExists = await testSubjects.descendantExists(values[i], tagCloud); + if (!valueExists) { + return false; + } + } + return true; + })); + expect(matches.indexOf(true)).to.be.greaterThan(-1); + } + + async goalAndGuageLabelsExist(labels) { + await this.textWithinCssElementExists(labels, '.chart-label'); + } + + async metricValuesExist(values) { + await this.textWithinCssElementExists(values, '.metric-value'); + } + + async tsvbMetricValuesExist(values) { + await this.textWithinTestSubjectsExists(values, 'tsvbMetricValue'); + } + + async tsvbTopNValuesExist(values) { + await this.textWithinTestSubjectsExists(values, 'tsvbTopNValue'); + } + + async vegaTextsExist(values) { + await this.textWithinCssElementExists(values, '.vega-view-container text'); + } + + async vegaTextsDoNotExist(values) { + await this.textWithinCssElementDoNotExist(values, '.vega-view-container text'); + } + + async tsvbMarkdownWithValuesExists(values) { + await this.textWithinTestSubjectsExists(values, 'tsvbMarkdown'); + } + + async markdownWithValuesExists(values) { + await this.textWithinTestSubjectsExists(values, 'markdownBody'); + } + + async savedSearchRowCount(expectedCount) { + await retry.try(async () => { + const savedSearchRows = await testSubjects.findAll('docTableExpandToggleColumn'); + expect(savedSearchRows.length).to.be(expectedCount); + }); + } + + async dataTableRowCount(expectedCount) { + await retry.try(async () => { + const dataTableRows = + await find.allByCssSelector('[data-test-subj="paginated-table-body"] [data-cell-content]'); + expect(dataTableRows.length).to.be(expectedCount); + }); + } + + async seriesElementCount(expectedCount) { + await retry.try(async () => { + const seriesElements = await find.allByCssSelector('.series'); + expect(seriesElements.length).to.be(expectedCount); + }); + } + + async inputControlItemCount(expectedCount) { + await retry.try(async () => { + const inputControlItems = await testSubjects.findAll('inputControlItem'); + expect(inputControlItems.length).to.be(expectedCount); + }); + } + + async lineChartPointsCount(expectedCount) { + await retry.try(async () => { + const points = await find.allByCssSelector('.points'); + expect(points.length).to.be(expectedCount); + }); + } + + async tsvbTableCellCount(expectedCount) { + await retry.try(async () => { + const tableCells = await find.allByCssSelector('.tsvb-table__value'); + expect(tableCells.length).to.be(expectedCount); + }); + } }; } diff --git a/test/functional/services/dashboard/index.js b/test/functional/services/dashboard/index.js index 881f88c250b327..53dfe381a1dc0e 100644 --- a/test/functional/services/dashboard/index.js +++ b/test/functional/services/dashboard/index.js @@ -1,2 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { DashboardVisualizationProvider } from './visualizations'; export { DashboardExpectProvider } from './expectations'; +export { DashboardAddPanelProvider } from './add_panel'; +export { DashboardPanelActionsProvider } from './panel_actions'; diff --git a/test/functional/services/dashboard/panel_actions.js b/test/functional/services/dashboard/panel_actions.js new file mode 100644 index 00000000000000..ca554e84fefe0d --- /dev/null +++ b/test/functional/services/dashboard/panel_actions.js @@ -0,0 +1,159 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const REMOVE_PANEL_DATA_TEST_SUBJ = 'dashboardPanelAction-deletePanel'; +const EDIT_PANEL_DATA_TEST_SUBJ = 'dashboardPanelAction-editPanel'; +const TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ = 'dashboardPanelAction-togglePanel'; +const CUSTOMIZE_PANEL_DATA_TEST_SUBJ = 'dashboardPanelAction-customizePanel'; +const OPEN_CONTEXT_MENU_ICON_DATA_TEST_SUBJ = 'dashboardPanelToggleMenuIcon'; + +export function DashboardPanelActionsProvider({ getService, getPageObjects }) { + const log = getService('log'); + const retry = getService('retry'); + const remote = getService('remote'); + const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects(['header', 'common']); + + return new class DashboardPanelActions { + + async isContextMenuOpen(parent) { + log.debug('isContextMenuOpen'); + // Full screen toggle was chosen because it's available in both view and edit mode. + return this.toggleExpandActionExists(parent); + } + + async findContextMenu(parent) { + return parent ? + await testSubjects.findDescendant(OPEN_CONTEXT_MENU_ICON_DATA_TEST_SUBJ, parent) : + await testSubjects.find(OPEN_CONTEXT_MENU_ICON_DATA_TEST_SUBJ); + } + + async isContextMenuIconVisible() { + log.debug('isContextMenuIconVisible'); + return await testSubjects.exists(OPEN_CONTEXT_MENU_ICON_DATA_TEST_SUBJ); + } + + async openContextMenu(parent) { + log.debug('openContextMenu'); + const panelOpen = await this.isContextMenuOpen(parent); + if (!panelOpen) { + await retry.try(async () => { + await (parent ? remote.moveMouseTo(parent) : testSubjects.moveMouseTo('dashboardPanelTitle')); + const toggleMenuItem = await this.findContextMenu(parent); + await toggleMenuItem.click(); + const panelOpen = await this.isContextMenuOpen(parent); + if (!panelOpen) { throw new Error('Context menu still not open'); } + }); + } + } + + async toggleExpandPanel(parent) { + log.debug('toggleExpandPanel'); + await (parent ? remote.moveMouseTo(parent) : testSubjects.moveMouseTo('dashboardPanelTitle')); + const expandShown = await this.toggleExpandActionExists(); + if (!expandShown) { + await this.openContextMenu(parent); + } + await this.toggleExpandPanel(); + } + + async clickEdit() { + log.debug('clickEdit'); + await this.openContextMenu(); + + // Edit link may sometimes be disabled if the embeddable isn't rendered yet. + await retry.try(async () => { + const editExists = await this.editPanelActionExists(); + if (editExists) { + await testSubjects.click(EDIT_PANEL_DATA_TEST_SUBJ); + } + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.common.waitForTopNavToBeVisible(); + const current = await remote.getCurrentUrl(); + if (current.indexOf('dashboard') >= 0) { + throw new Error('Still on dashboard'); + } + }); + } + + async toggleExpandPanel() { + log.debug('toggleExpandPanel'); + await this.openContextMenu(); + await testSubjects.click(TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ); + } + + async removePanel() { + log.debug('removePanel'); + await this.openContextMenu(); + await testSubjects.click(REMOVE_PANEL_DATA_TEST_SUBJ); + } + + async customizePanel(parent) { + await this.openContextMenu(parent); + await testSubjects.click(CUSTOMIZE_PANEL_DATA_TEST_SUBJ); + } + + async removePanelActionExists() { + log.debug('removePanelActionExists'); + return await testSubjects.exists(REMOVE_PANEL_DATA_TEST_SUBJ); + } + + async editPanelActionExists() { + log.debug('editPanelActionExists'); + return await testSubjects.exists(EDIT_PANEL_DATA_TEST_SUBJ); + } + + async toggleExpandActionExists() { + log.debug('toggleExpandActionExists'); + return await testSubjects.exists(TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ); + } + + async customizePanelActionExists(parent) { + return parent ? + await testSubjects.descendantExists(CUSTOMIZE_PANEL_DATA_TEST_SUBJ, parent) : + await testSubjects.exists(CUSTOMIZE_PANEL_DATA_TEST_SUBJ); + } + + async getPanelHeading(title) { + return await testSubjects.find(`dashboardPanelHeading-${title.replace(/\s/g, '')}`); + } + + /** + * + * @param customTitle + * @param originalTitle - optional to specify which panel to change the title on. + * @return {Promise} + */ + async setCustomPanelTitle(customTitle, originalTitle) { + log.debug(`setCustomPanelTitle(${customTitle}, ${originalTitle})`); + let panelOptions = null; + if (originalTitle) { + panelOptions = await this.getPanelHeading(originalTitle); + } + await this.customizePanel(panelOptions); + await testSubjects.setValue('customDashboardPanelTitleInput', customTitle); + } + + async resetCustomPanelTitle(panel) { + log.debug('resetCustomPanelTitle'); + await this.customizePanel(panel); + await testSubjects.click('resetCustomDashboardPanelTitle'); + } + }; +} diff --git a/test/functional/services/dashboard/visualizations.js b/test/functional/services/dashboard/visualizations.js index 40ac4225b6526e..0d3ea8cf4d2574 100644 --- a/test/functional/services/dashboard/visualizations.js +++ b/test/functional/services/dashboard/visualizations.js @@ -1,7 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function DashboardVisualizationProvider({ getService, getPageObjects }) { const log = getService('log'); + const queryBar = getService('queryBar'); const testSubjects = getService('testSubjects'); + const dashboardAddPanel = getService('dashboardAddPanel'); const PageObjects = getPageObjects(['dashboard', 'visualize', 'header', 'discover']); return new class DashboardVisualizations { @@ -11,8 +32,8 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) { if (inViewMode) { await PageObjects.dashboard.clickEdit(); } - await PageObjects.dashboard.clickAddVisualization(); - await PageObjects.dashboard.clickAddNewVisualizationLink(); + await dashboardAddPanel.ensureAddPanelIsShowing(); + await dashboardAddPanel.clickAddNewEmbeddableLink(); await PageObjects.visualize.clickVisualBuilder(); await PageObjects.visualize.saveVisualization(name); } @@ -21,11 +42,11 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) { log.debug(`createSavedSearch(${name})`); await PageObjects.header.clickDiscover(); - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); if (query) { - await PageObjects.dashboard.setQuery(query); - await PageObjects.dashboard.clickFilterButton(); + await queryBar.setQuery(query); + await queryBar.submitQuery(); } if (fields) { @@ -49,7 +70,7 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) { if (inViewMode) { await PageObjects.dashboard.clickEdit(); } - await PageObjects.dashboard.addSavedSearch(name); + await dashboardAddPanel.addSavedSearch(name); } async createAndAddMarkdown({ name, markdown }) { @@ -58,8 +79,8 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) { if (inViewMode) { await PageObjects.dashboard.clickEdit(); } - await PageObjects.dashboard.clickAddVisualization(); - await PageObjects.dashboard.clickAddNewVisualizationLink(); + await dashboardAddPanel.ensureAddPanelIsShowing(); + await dashboardAddPanel.clickAddNewEmbeddableLink(); await PageObjects.visualize.clickMarkdownWidget(); await PageObjects.visualize.setMarkdownTxt(markdown); await PageObjects.visualize.clickGo(); diff --git a/test/functional/services/doc_table.js b/test/functional/services/doc_table.js index 523accee3f70fd..aa44139c80eb22 100644 --- a/test/functional/services/doc_table.js +++ b/test/functional/services/doc_table.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function DocTableProvider({ getService }) { const testSubjects = getService('testSubjects'); const retry = getService('retry'); diff --git a/test/functional/services/failure_debugging.js b/test/functional/services/failure_debugging.js index 78e354d5114bd0..ed2ac4258545d7 100644 --- a/test/functional/services/failure_debugging.js +++ b/test/functional/services/failure_debugging.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve } from 'path'; import { writeFile } from 'fs'; import mkdirp from 'mkdirp'; diff --git a/test/functional/services/filter_bar.js b/test/functional/services/filter_bar.js index 4b3ebb5f790e9b..43a1c1265a1833 100644 --- a/test/functional/services/filter_bar.js +++ b/test/functional/services/filter_bar.js @@ -1,8 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function FilterBarProvider({ getService }) { const remote = getService('remote'); const testSubjects = getService('testSubjects'); const find = getService('find'); + async function typeIntoReactSelect(testSubj, value) { + const select = await testSubjects.find(testSubj); + const input = await select.findByClassName('ui-select-search'); + await input.type(value); + const activeSelection = await select.findByClassName('active'); + await activeSelection.click(); + } + class FilterBar { hasFilter(key, value, enabled = true) { const filterActivationState = enabled ? 'enabled' : 'disabled'; @@ -23,17 +50,25 @@ export function FilterBarProvider({ getService }) { await testSubjects.click(`filter & filter-key-${key} disableFilter-${key}`); } - async addFilter(field, operator, value) { + async addFilter(field, operator, values) { + if (!Array.isArray(values)) { + values = [values]; + } await testSubjects.click('addFilter'); - let input = await find.byCssSelector(`filter-field-select input.ui-select-search`); - await input.type(field); - await remote.pressKeys('\uE006'); - input = await find.byCssSelector(`filter-operator-select input.ui-select-search`); - await input.type(operator); - await remote.pressKeys('\uE006'); - input = await find.byCssSelector(`filter-params-editor input.ui-select-search`); - await input.type(value); - await remote.pressKeys('\uE006'); + await typeIntoReactSelect('filterfieldSuggestionList', field); + await typeIntoReactSelect('filterOperatorList', operator); + const params = await testSubjects.find('filterParams'); + const paramFields = await params.findAllByTagName('input'); + await Promise.all(values.map(async (value, index) => { + await paramFields[index].type(value); + // Checks if the actual options value has an auto complete (like 'is one of' filter) + // In this case we need to click the active autocompletion. + const hasAutocompletion = await find.exists(async () => await params.findByClassName('active')); + if (hasAutocompletion) { + const activeSelection = await params.findByClassName('active'); + await activeSelection.click(); + } + })); await testSubjects.click('saveFilter'); } @@ -48,6 +83,13 @@ export function FilterBarProvider({ getService }) { return await Promise.all(spans.map(el => el.getVisibleText())); } + async ensureFieldEditorModalIsClosed() { + const closeFilterEditorModalButtonExists = await testSubjects.exists('filterEditorModalCloseButton'); + if (closeFilterEditorModalButtonExists) { + await testSubjects.click('filterEditorModalCloseButton'); + } + } + async getFilterFieldIndexPatterns() { const indexPatterns = []; const groups = await find.allByCssSelector('.ui-select-choices-group-label'); diff --git a/test/functional/services/find.js b/test/functional/services/find.js index 8922faa222f919..d374b332def02d 100644 --- a/test/functional/services/find.js +++ b/test/functional/services/find.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export function FindProvider({ getService }) { const log = getService('log'); const config = getService('config'); @@ -53,6 +72,20 @@ export function FindProvider({ getService }) { }); } + async setValue(selector, text) { + return await retry.try(async () => { + const element = await this.byCssSelector(selector); + await element.click(); + + // in case the input element is actually a child of the testSubject, we + // call clearValue() and type() on the element that is focused after + // clicking on the testSubject + const input = await remote.getActiveElement(); + await input.clearValue(); + await input.type(text); + }); + } + async allByCustom(findAllFunction, timeout = defaultFindTimeout) { return await this._withTimeout(timeout, async remote => { return await retry.try(async () => { @@ -136,6 +169,7 @@ export function FindProvider({ getService }) { log.debug(`clickByPartialLinkText(${linkText})`); await retry.try(async () => { const element = await this.byPartialLinkText(linkText, timeout); + await remote.moveMouseTo(element); await element.click(); }); } @@ -144,6 +178,7 @@ export function FindProvider({ getService }) { log.debug(`clickByLinkText(${linkText})`); await retry.try(async () => { const element = await this.byLinkText(linkText, timeout); + await remote.moveMouseTo(element); await element.click(); }); } @@ -152,6 +187,7 @@ export function FindProvider({ getService }) { log.debug(`clickByCssSelector(${selector})`); await retry.try(async () => { const element = await this.byCssSelector(selector, timeout); + await remote.moveMouseTo(element); await element.click(); }); } diff --git a/test/functional/services/index.js b/test/functional/services/index.js index 795164fc593f62..c637a46e467229 100644 --- a/test/functional/services/index.js +++ b/test/functional/services/index.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { QueryBarProvider } from './query_bar'; export { FilterBarProvider } from './filter_bar'; export { FindProvider } from './find'; @@ -6,4 +25,6 @@ export { RemoteProvider } from './remote'; export { DocTableProvider } from './doc_table'; export { ScreenshotsProvider } from './screenshots'; export { FailureDebuggingProvider } from './failure_debugging'; +export { VisualizeListingTableProvider } from './visualize_listing_table'; + export * from './dashboard'; diff --git a/test/functional/services/lib/compare_pngs.js b/test/functional/services/lib/compare_pngs.js index 6ed2f09dca6b37..7f9ab50fab713a 100644 --- a/test/functional/services/lib/compare_pngs.js +++ b/test/functional/services/lib/compare_pngs.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import path from 'path'; import Jimp from 'jimp'; diff --git a/test/functional/services/query_bar.js b/test/functional/services/query_bar.js index 2ef7e62909756b..0056821b81c762 100644 --- a/test/functional/services/query_bar.js +++ b/test/functional/services/query_bar.js @@ -1,11 +1,51 @@ -export function QueryBarProvider({ getService }) { +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export function QueryBarProvider({ getService, getPageObjects }) { const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + const log = getService('log'); + const PageObjects = getPageObjects(['header']); class QueryBar { async getQueryString() { - const queryInput = await testSubjects.find('queryInput'); - return await queryInput.getProperty('value'); + return await testSubjects.getProperty('queryInput', 'value'); + } + + async setQuery(query) { + log.debug(`QueryBar.setQuery(${query})`); + // Extra caution used because of flaky test here: https://github.com/elastic/kibana/issues/16978 doesn't seem + // to be actually setting the query in the query input based off + await retry.try(async () => { + await testSubjects.setValue('queryInput', query); + const currentQuery = await this.getQueryString(); + if (currentQuery !== query) { + throw new Error(`Failed to set query input to ${query}, instead query is ${currentQuery}`); + } + }); + } + + async submitQuery() { + log.debug('QueryBar.submitQuery'); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); } } diff --git a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/config.js b/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/config.js index fefe50bcc4fb16..c5074165b7ec25 100644 --- a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/config.js +++ b/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/config.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { RemoteProvider } from '../../../remote'; export default function () { diff --git a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test.js b/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test.js index 70fe781a5593fb..fe54896111be48 100644 --- a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test.js +++ b/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, loadTestFile }) { const remote = getService('remote'); diff --git a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test2.js b/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test2.js index 0a786e22b68bf0..4e7092f915272c 100644 --- a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test2.js +++ b/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test2.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService }) { const remote = getService('remote'); diff --git a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.1.js b/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.1.js index 3ca760f3dca71c..5960cac0514c55 100644 --- a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.1.js +++ b/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.1.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService }) { const remote = getService('remote'); diff --git a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.js b/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.js index 7db3d2b49419b0..8ac398b74d1c92 100644 --- a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.js +++ b/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export default function ({ getService, loadTestFile }) { const remote = getService('remote'); diff --git a/test/functional/services/remote/__tests__/remote_default_window_size.js b/test/functional/services/remote/__tests__/remote_default_window_size.js index ed6b1e25223d64..ffa66bcc7c892a 100644 --- a/test/functional/services/remote/__tests__/remote_default_window_size.js +++ b/test/functional/services/remote/__tests__/remote_default_window_size.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { fork } from 'child_process'; import expect from 'expect.js'; diff --git a/test/functional/services/remote/browser_driver_api/browser_driver_api.js b/test/functional/services/remote/browser_driver_api/browser_driver_api.js index 4778ec8dfa0657..57d7bd93b3629c 100644 --- a/test/functional/services/remote/browser_driver_api/browser_driver_api.js +++ b/test/functional/services/remote/browser_driver_api/browser_driver_api.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { EventEmitter } from 'events'; import { createLocalBrowserDriverApi } from './browser_driver_local_api'; diff --git a/test/functional/services/remote/browser_driver_api/browser_driver_local_api.js b/test/functional/services/remote/browser_driver_api/browser_driver_local_api.js index 1ba0183723bf17..9cbb029cf4014a 100644 --- a/test/functional/services/remote/browser_driver_api/browser_driver_local_api.js +++ b/test/functional/services/remote/browser_driver_api/browser_driver_local_api.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { spawn } from 'child_process'; import { parse as parseUrl } from 'url'; diff --git a/test/functional/services/remote/browser_driver_api/browser_driver_remote_api.js b/test/functional/services/remote/browser_driver_api/browser_driver_remote_api.js index 5946bc3cdd3c10..3b8e486c2e55f9 100644 --- a/test/functional/services/remote/browser_driver_api/browser_driver_remote_api.js +++ b/test/functional/services/remote/browser_driver_api/browser_driver_remote_api.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { BrowserDriverApi } from './browser_driver_api'; export function createRemoteBrowserDriverApi(log, url) { diff --git a/test/functional/services/remote/browser_driver_api/index.js b/test/functional/services/remote/browser_driver_api/index.js index 7b85aa096de57d..acc228e17086f2 100644 --- a/test/functional/services/remote/browser_driver_api/index.js +++ b/test/functional/services/remote/browser_driver_api/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { BrowserDriverApi } from './browser_driver_api'; diff --git a/test/functional/services/remote/browser_driver_api/ping.js b/test/functional/services/remote/browser_driver_api/ping.js index 6507aebdd7371d..65b62a8b7b4dc3 100644 --- a/test/functional/services/remote/browser_driver_api/ping.js +++ b/test/functional/services/remote/browser_driver_api/ping.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import request from 'request'; import { fromNode as fcb } from 'bluebird'; diff --git a/test/functional/services/remote/index.js b/test/functional/services/remote/index.js index 58e8d54cde3557..0ba58d1a3e3b04 100644 --- a/test/functional/services/remote/index.js +++ b/test/functional/services/remote/index.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + export { RemoteProvider } from './remote'; diff --git a/test/functional/services/remote/interceptors.js b/test/functional/services/remote/interceptors.js index f973e1b150d4c2..2b2b5792eac9f8 100644 --- a/test/functional/services/remote/interceptors.js +++ b/test/functional/services/remote/interceptors.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { modifyUrl } from '../../../../src/utils'; export const createRemoteInterceptors = remote => ({ diff --git a/test/functional/services/remote/leadfoot_command.js b/test/functional/services/remote/leadfoot_command.js index 7af2e380e6401a..732cbc5afcdfd6 100644 --- a/test/functional/services/remote/leadfoot_command.js +++ b/test/functional/services/remote/leadfoot_command.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { delay } from 'bluebird'; import Command from 'leadfoot/Command'; import Server from 'leadfoot/Server'; diff --git a/test/functional/services/remote/remote.js b/test/functional/services/remote/remote.js index 5cada9cb00dc4f..c74751d404cc82 100644 --- a/test/functional/services/remote/remote.js +++ b/test/functional/services/remote/remote.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { initLeadfootCommand } from './leadfoot_command'; import { createRemoteInterceptors } from './interceptors'; import { BrowserDriverApi } from './browser_driver_api'; diff --git a/test/functional/services/remote/verbose_remote_logging.js b/test/functional/services/remote/verbose_remote_logging.js index 0614d16a7fa3fd..42ea4f7e00f85e 100644 --- a/test/functional/services/remote/verbose_remote_logging.js +++ b/test/functional/services/remote/verbose_remote_logging.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { green, magentaBright } from 'chalk'; export function initVerboseRemoteLogging(log, server) { diff --git a/test/functional/services/screenshots.js b/test/functional/services/screenshots.js index e5d55f40a0b17b..9c4b9a93178857 100644 --- a/test/functional/services/screenshots.js +++ b/test/functional/services/screenshots.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import { resolve, dirname } from 'path'; import { writeFile, readFileSync } from 'fs'; import { fromNode as fcb, promisify } from 'bluebird'; diff --git a/test/functional/services/test_subjects.js b/test/functional/services/test_subjects.js index 59c362a619c7ac..f40600e71128b7 100644 --- a/test/functional/services/test_subjects.js +++ b/test/functional/services/test_subjects.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import testSubjSelector from '@kbn/test-subj-selector'; import { filter as filterAsync, @@ -48,9 +67,9 @@ export function TestSubjectsProvider({ getService }) { return await find.byCssSelector(testSubjSelector(selector), timeout); } - async findAll(selector) { + async findAll(selector, timeout) { log.debug(`TestSubjects.findAll(${selector})`); - const all = await find.allByCssSelector(testSubjSelector(selector)); + const all = await find.allByCssSelector(testSubjSelector(selector), timeout); return await filterAsync(all, el => el.isDisplayed()); } diff --git a/test/functional/services/visualize_listing_table.js b/test/functional/services/visualize_listing_table.js new file mode 100644 index 00000000000000..e38a214b50801d --- /dev/null +++ b/test/functional/services/visualize_listing_table.js @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export function VisualizeListingTableProvider({ getService, getPageObjects }) { + const testSubjects = getService('testSubjects'); + const find = getService('find'); + const log = getService('log'); + const PageObjects = getPageObjects(['dashboard', 'visualize', 'header', 'discover']); + + class VisualizeListingTable { + async getAllVisualizationNamesOnCurrentPage() { + const visualizationNames = []; + const links = await find.allByCssSelector('.kuiLink'); + for (let i = 0; i < links.length; i++) { + visualizationNames.push(await links[i].getVisibleText()); + } + log.debug(`Found ${visualizationNames.length} visualizations on current page`); + return visualizationNames; + } + + async getAllVisualizationNames() { + log.debug('VisualizeListingTable.getAllVisualizationNames'); + let morePages = true; + let visualizationNames = []; + while (morePages) { + visualizationNames = visualizationNames.concat(await this.getAllVisualizationNamesOnCurrentPage()); + const pagerNextButton = await testSubjects.find('pagerNextButton'); + morePages = !(await pagerNextButton.getProperty('disabled')); + if (morePages) { + await testSubjects.click('pagerNextButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + } + } + return visualizationNames; + } + } + + return new VisualizeListingTable(); +} diff --git a/test/kibana_test_server_url_parts.js b/test/kibana_test_server_url_parts.js deleted file mode 100644 index e8d8a48d1a778d..00000000000000 --- a/test/kibana_test_server_url_parts.js +++ /dev/null @@ -1,30 +0,0 @@ -import { kibanaUser } from './shield'; -import url from 'url'; - -function getUrlParts() { - // allow setting one complete TEST_KIBANA_URL for ES like https://elastic:changeme@example.com:9200 - if (process.env.TEST_KIBANA_URL) { - const testKibanaUrl = url.parse(process.env.TEST_KIBANA_URL); - return { - protocol: testKibanaUrl.protocol.slice(0, -1), - hostname: testKibanaUrl.hostname, - port: parseInt(testKibanaUrl.port, 10), - auth: testKibanaUrl.auth, - username: testKibanaUrl.auth.split(':')[0], - password: testKibanaUrl.auth.split(':')[1] - }; - } - - const username = process.env.TEST_KIBANA_USERNAME || kibanaUser.username; - const password = process.env.TEST_KIBANA_PASSWORD || kibanaUser.password; - return { - protocol: process.env.TEST_KIBANA_PROTOCOL || 'http', - hostname: process.env.TEST_KIBANA_HOSTNAME || 'localhost', - port: parseInt(process.env.TEST_KIBANA_PORT, 10) || 5620, - auth: `${username}:${password}`, - username, - password, - }; -} - -export const kibanaTestServerUrlParts = getUrlParts(); diff --git a/test/mocha.opts b/test/mocha.opts deleted file mode 100644 index a4d588165948ab..00000000000000 --- a/test/mocha.opts +++ /dev/null @@ -1 +0,0 @@ ---require src/babel-register diff --git a/test/scripts/jenkins_docs.sh b/test/scripts/jenkins_docs.sh index 176f314779c475..bd606d60101d84 100755 --- a/test/scripts/jenkins_docs.sh +++ b/test/scripts/jenkins_docs.sh @@ -3,4 +3,4 @@ set -e source "$(dirname $0)/../../src/dev/ci_setup/setup.sh" -"$(yarn bin)/grunt" jenkins:docs; +"$(FORCE_COLOR=0 yarn bin)/grunt" jenkins:docs; diff --git a/test/scripts/jenkins_selenium.sh b/test/scripts/jenkins_selenium.sh index b608057408aab7..7d6b26a59c485c 100755 --- a/test/scripts/jenkins_selenium.sh +++ b/test/scripts/jenkins_selenium.sh @@ -7,4 +7,4 @@ source "$(dirname $0)/../../src/dev/ci_setup/java_setup.sh" node scripts/build --release --debug --oss; -xvfb-run "$(yarn bin)/grunt" jenkins:selenium --from=source; +xvfb-run "$(FORCE_COLOR=0 yarn bin)/grunt" jenkins:selenium --from=source; diff --git a/test/scripts/jenkins_unit.sh b/test/scripts/jenkins_unit.sh index 57611f6719ca33..0ce41c45110fdb 100755 --- a/test/scripts/jenkins_unit.sh +++ b/test/scripts/jenkins_unit.sh @@ -6,4 +6,4 @@ source "$(dirname $0)/../../src/dev/ci_setup/git_setup.sh" source "$(dirname $0)/../../src/dev/ci_setup/java_setup.sh" export TEST_ES_FROM=source -xvfb-run "$(yarn bin)/grunt" jenkins:unit --from=source; +xvfb-run "$(FORCE_COLOR=0 yarn bin)/grunt" jenkins:unit --from=source; diff --git a/test/scripts/jenkins_xpack.sh b/test/scripts/jenkins_xpack.sh index 90ed0dc884ab42..6207a9fc78fb84 100755 --- a/test/scripts/jenkins_xpack.sh +++ b/test/scripts/jenkins_xpack.sh @@ -35,14 +35,7 @@ mkdir -p "$installDir" tar -xzf "$linuxBuild" -C "$installDir" --strip=1 -echo " -> Running api integration tests" -cd "$XPACK_DIR" -node scripts/functional_tests_api --kibana-install-dir "$installDir" --es-from=source -echo "" -echo "" - - -echo " -> Running functional tests" +echo " -> Running functional and api tests" cd "$XPACK_DIR" xvfb-run node scripts/functional_tests --bail --kibana-install-dir "$installDir" --es-from=source echo "" diff --git a/test/scripts/run_mocha.js b/test/scripts/run_mocha.js deleted file mode 100644 index 0e53f6071197ce..00000000000000 --- a/test/scripts/run_mocha.js +++ /dev/null @@ -1,14 +0,0 @@ -const debugInBand = process.execArgv.some(arg => { - switch (arg) { - case '--inspect': - case '--inspect-brk': - return true; - } -}); - -if (debugInBand) { - process.argv.push('--no-timeouts'); - require('mocha/bin/_mocha'); -} else { - require('mocha/bin/mocha'); -} diff --git a/test/shield.js b/test/shield.js deleted file mode 100644 index eb4fdcd4a22e60..00000000000000 --- a/test/shield.js +++ /dev/null @@ -1,16 +0,0 @@ -const env = process.env; - -export const kibanaUser = { - username: env.TEST_KIBANA_USER || 'elastic', - password: env.TEST_KIBANA_PASS || 'changeme' -}; - -export const kibanaServer = { - username: env.TEST_KIBANA_SERVER_USER || 'kibana', - password: env.TEST_KIBANA_SERVER_PASS || 'changeme' -}; - -export const admin = { - username: env.TEST_ES_USER || 'elastic', - password: env.TEST_ES_PASS || 'changeme' -}; diff --git a/tsconfig.json b/tsconfig.json index 4b2b96f4aa0506..eb218de056e4bb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,19 +1,28 @@ { "compilerOptions": { + "baseUrl": ".", + + // Support .tsx files and transform JSX into calls to React.createElement + "jsx": "react", + // Enables all strict type checking options. "strict": true, - // Library files to be included in the compilation. Basically which "core - // language features" TypeScript should enable. - "lib": ["es2015", "es2016", "es2017"], + // enables "core language features" + "lib": [ + // ESNext auto includes previous versions all the way back to es5 + "esnext", + // includes support for browser APIs + "dom" + ], - // Which version of EcmaScript TypeScript should transpile to. Because of - // how Babel and Webpack is set up we currently target `esnext`, and let - // Babel take care of transpiling it down. + // Node 8 should support everything output by esnext, we override this + // in webpack with loader-level compiler options "target": "esnext", - // Specifies module code generation. - "module": "esnext", + // Use commonjs for node, overriden in webpack to keep import statements + // to maintain support for things like `await import()` + "module": "commonjs", // Allows default imports from modules with no default export. This does not affect code emit, just type checking. // We have to enable this option explicitly since `esModuleInterop` doesn't enable it automatically when ES2015 or @@ -28,14 +37,9 @@ "moduleResolution": "node", // Disallow inconsistently-cased references to the same file. - "forceConsistentCasingInFileNames": true, - - // Generate an external source map. There's also an `--inlineSourceMap` for - // emitting a single file with source maps instead of having a separate file. - "sourceMap": true + "forceConsistentCasingInFileNames": true }, - - "exclude": [ - "node_modules" + "include": [ + "src/**/*" ] } diff --git a/tslint.yaml b/tslint.yaml new file mode 100644 index 00000000000000..17cf048195317b --- /dev/null +++ b/tslint.yaml @@ -0,0 +1,33 @@ +extends: + - tslint:recommended + - tslint-config-prettier + +rulesDirectory: + - tslint-plugin-prettier + - src/dev/tslint/rules + +rules: + prettier: true + no-unused-variable: true + interface-name: false + require-license-header: + - true + - |- + /* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ diff --git a/utilities/visual_regression.js b/utilities/visual_regression.js index 9efce63dff2eb9..f117f503bdb9cf 100644 --- a/utilities/visual_regression.js +++ b/utilities/visual_regression.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import bluebird, { fromNode, promisify, diff --git a/webpackShims/ace.js b/webpackShims/ace.js index 0386937dacb030..e411b46a7a405f 100644 --- a/webpackShims/ace.js +++ b/webpackShims/ace.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('brace'); require('brace/mode/json'); require('../node_modules/@elastic/ui-ace/ui-ace'); diff --git a/webpackShims/angular-ui-select.js b/webpackShims/angular-ui-select.js index 95e0ac8b912616..2b88836fc97f1d 100644 --- a/webpackShims/angular-ui-select.js +++ b/webpackShims/angular-ui-select.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('jquery'); require('angular'); require('angular-sanitize'); diff --git a/webpackShims/angular.js b/webpackShims/angular.js index edb11f623fcded..ab7fc06bf3c282 100644 --- a/webpackShims/angular.js +++ b/webpackShims/angular.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('jquery'); require('../node_modules/angular/angular'); module.exports = window.angular; diff --git a/webpackShims/elasticsearch-browser.js b/webpackShims/elasticsearch-browser.js index 85f11933ae1fa4..d8d7e439a129e2 100644 --- a/webpackShims/elasticsearch-browser.js +++ b/webpackShims/elasticsearch-browser.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('angular'); module.exports = require('elasticsearch-browser/elasticsearch.angular.js'); require('ui/modules').get('kibana', ['elasticsearch']); diff --git a/webpackShims/elasticsearch.js b/webpackShims/elasticsearch.js index 07fc22241ba8e2..fcf1ccc68dab51 100644 --- a/webpackShims/elasticsearch.js +++ b/webpackShims/elasticsearch.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = false; throw new Error('The elasticsearch npm module is not designed for use in the browser. Please use elasticsearch-browser'); diff --git a/webpackShims/jquery.js b/webpackShims/jquery.js index a0be5a31b83c70..3fd7af45f12deb 100644 --- a/webpackShims/jquery.js +++ b/webpackShims/jquery.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var $ = window.jQuery = window.$ = module.exports = require('../node_modules/jquery/dist/jquery'); require('ui/jquery/find_test_subject')($); diff --git a/webpackShims/leaflet.js b/webpackShims/leaflet.js index 9ac495305345f5..c35076e1295339 100644 --- a/webpackShims/leaflet.js +++ b/webpackShims/leaflet.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('../node_modules/leaflet/dist/leaflet.css'); window.L = module.exports = require('../node_modules/leaflet/dist/leaflet'); window.L.Browser.touch = false; diff --git a/webpackShims/mocha.js b/webpackShims/mocha.js index 865e84ee8e658e..9ab12381b643c5 100644 --- a/webpackShims/mocha.js +++ b/webpackShims/mocha.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = require('../node_modules/mocha/mocha.js'); diff --git a/webpackShims/moment-timezone.js b/webpackShims/moment-timezone.js index 3781ad0ab3f9d9..91bcc0cd1391ce 100644 --- a/webpackShims/moment-timezone.js +++ b/webpackShims/moment-timezone.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + var moment = module.exports = require('../node_modules/moment-timezone/moment-timezone'); moment.tz.load(require('../node_modules/moment-timezone/data/packed/latest.json')); diff --git a/webpackShims/moment.js b/webpackShims/moment.js index 397cffc1dda22c..c6aca40432a85b 100644 --- a/webpackShims/moment.js +++ b/webpackShims/moment.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = require('../node_modules/moment/min/moment.min.js'); diff --git a/webpackShims/numeral.js b/webpackShims/numeral.js index b63aba6c7ce5a5..d9551e05aa6d6e 100644 --- a/webpackShims/numeral.js +++ b/webpackShims/numeral.js @@ -1 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + module.exports = require('@elastic/numeral'); diff --git a/webpackShims/sinon.js b/webpackShims/sinon.js index 9ffc5171cfaa3b..e201f405fb127a 100644 --- a/webpackShims/sinon.js +++ b/webpackShims/sinon.js @@ -1,2 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('script-loader!../node_modules/sinon/pkg/sinon.js'); module.exports = window.sinon; diff --git a/webpackShims/ui-bootstrap.js b/webpackShims/ui-bootstrap.js index 64b977a72edacd..e8354018e6c18c 100644 --- a/webpackShims/ui-bootstrap.js +++ b/webpackShims/ui-bootstrap.js @@ -1,3 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + require('angular'); require('ui/angular-bootstrap'); var uiModules = require('ui/modules').uiModules; diff --git a/x-pack/.gitignore b/x-pack/.gitignore index 728c1b9a7d5e94..7e582d057eac4d 100644 --- a/x-pack/.gitignore +++ b/x-pack/.gitignore @@ -1,6 +1,7 @@ /.gradle /build /target +/test/functional/failure_debug /test/functional/screenshots /test/functional/apps/reporting/reports/session /plugins/reporting/.chromium/ diff --git a/x-pack/.kibana-plugin-helpers.json b/x-pack/.kibana-plugin-helpers.json index 6faacc9aa0a0ad..5120016237f71d 100644 --- a/x-pack/.kibana-plugin-helpers.json +++ b/x-pack/.kibana-plugin-helpers.json @@ -9,6 +9,7 @@ "NOTICE.txt", "package.json", "yarn.lock", + "tsconfig.json", "index.js", "plugins/reporting/.phantom/*", "plugins/reporting/.chromium/*", diff --git a/x-pack/README.md b/x-pack/README.md index 8a2d0a1fccb6fd..63722ac16ab107 100644 --- a/x-pack/README.md +++ b/x-pack/README.md @@ -8,6 +8,10 @@ from files licensed under the Apache License 2.0. By default, Kibana will run with X-Pack installed as mentioned in the [contributing guide](../CONTRIBUTING.md). +Elasticsearch will run with a basic license. To run with a trial license, including security, you can specifying that with the `yarn es` command. + +Example: `yarn es snapshot --license trial --password changeme` + # Testing ## Running unit tests_bundle @@ -27,6 +31,12 @@ yarn test --plugins [,]* # where is "reporting", etc #### Running single test file Edit test file, changing top level `describe` to `describe.only`. Run tests with normal commands. +#### Running Jest Unit Tests +```bash +# from x-pack folder +node scripts/jest +``` + #### Debugging browser tests ``` yarn test:browser:dev @@ -44,7 +54,15 @@ yarn test:server #### Running functional tests -The functional tests are run against a live browser, Kibana, and Elasticsearch install. They build their own version of elasticsearch and x-pack-elasticsearch, run the builds automatically, startup the kibana server, and run the tests against them. +The functional UI tests, the API integration tests, and the SAML API integration tests are all run against a live browser, Kibana, and Elasticsearch install. Each set of tests is specified with a unique config that describes how to start the Elasticsearch server, the Kibana server, and what tests to run against them. The sets of tests that exist today are *functional UI tests* ([specified by this config](test/functional/config.js)), *API integration tests* ([specified by this config](test/api_integration/config.js)), and *SAML API integration tests* ([specified by this config](test/saml_api_integration/config.js)). + +The script runs all sets of tests sequentially like so: +* builds Elasticsearch and X-Pack +* runs Elasticsearch with X-Pack +* starts up the Kibana server with X-Pack +* runs the functional UI tests against those servers +* tears down the servers +* repeats the same process for the API and SAML API integration test configs. To do all of this in a single command run: @@ -52,61 +70,60 @@ To do all of this in a single command run: node scripts/functional_tests ``` -If you are **developing functional tests** then you probably don't want to rebuild elasticsearch and wait for all that setup on every test run, so instead use this command to get started: - -```sh -node scripts/functional_tests_server -``` +#### Running UI tests -After both Elasticsearch and Kibana are running, open a new terminal (without tearing down Elasticsearch, Kibana, etc.) and use the following to run the tests: +To run _only_ the functional UI tests: ```sh -# this command accepts a bunch of arguments to tweak the run, try sending --help to learn more -node ../scripts/functional_test_runner +node scripts/functional_tests --config test/functional/config ``` +It does the same as the previous command, except that it only does setup/test/teardown for the UI tests. + #### Running API integration tests -API integration tests are very similar to functional tests in a sense that they are organized in the same way and run against live Kibana and Elasticsearch instances. -The difference is that API integration tests are intended to test only programmatic API exposed by Kibana. There is no need to run browser and simulate user actions that significantly reduces execution time. +API integration tests are run with a unique setup usually without UI assets built for the Kibana server. -To build, run `x-pack-kibana` with `x-pack-elasticsearch` and then run API integration tests against them use the following command: +API integration tests are intended to test _only programmatic API exposed by Kibana_. There is no need to run browser and simulate user actions, which significantly reduces execution time. In addition, the configuration for API integration tests typically sets `optimize.enabled=false` for Kibana because UI assets are usually not needed for these tests. -```sh -node scripts/functional_tests_api -``` - -If you are **developing api integration tests** then you probably don't want to rebuild `x-pack-elasticsearch` and wait for all that setup on every test run, so instead use this command to get started: +To run _only_ the API integration tests: ```sh -node scripts/functional_tests_server +node scripts/functional_tests --config test/api_integration/config ``` -Once Kibana and Elasticsearch are up and running open a new terminal and run this command to just run the tests (without tearing down Elasticsearch, Kibana, etc.) +#### Running SAML API integration tests + +We also have SAML API integration tests which set up Elasticsearch and Kibana with SAML support. Run _only_ API integration tests with SAML enabled like so: ```sh -# this command accepts a bunch of arguments to tweak the run, try sending --help to learn more -node ../scripts/functional_test_runner --config test/api_integration/config.js +node scripts/functional_tests --config test/saml_api_integration/config ``` -You can also run API integration tests with SAML support. The `--saml` option configures both Kibana and Elasticsearch -with the SAML security realm, as required by the SAML security API. +#### Developing functional tests -Start the functional test server with SAML support: +If you are **developing functional tests** then you probably don't want to rebuild Elasticsearch and wait for all that setup on every test run, so instead use this command to build and start just the Elasticsearch and Kibana servers: ```sh -node scripts/functional_tests_server --saml +node scripts/functional_tests_server ``` -Then run the tests with: +After the servers are started, open a new terminal and run this command to run just the tests (without tearing down Elasticsearch or Kibana): + ```sh -# make sure you are in the x-pack-kibana project -cd x-pack-kibana +# Make sure you are in the x-pack directory +cd x-pack -# use a different config for SAML -node ../scripts/functional_test_runner --config test/saml_api_integration/config.js +# Invoke the functional_test_runner from Kibana. Try sending --help to learn more +node ../scripts/functional_test_runner ``` +For both of the above commands, it's crucial that you pass in `--config` to specify the same config file to both commands. This makes sure that the right tests will run against the right servers. Typically a set of tests and server configuration go together. + +Read more about how the scripts work [here](scripts/README.md). + +For a deeper dive, read more about the way functional tests and servers work [here](packages/kbn-test/README.md). + ### Issues starting dev more of creating builds You may see an error like this when you are getting started: @@ -121,55 +138,3 @@ That's thanks to the binary Phantom downloads that have to happen, and Bitbucket 1. Just keep re-running the command until it passes. Eventually the downloads will work, and since they are cached, it won't ever be an issue again. 1. Download them by hand [from Bitbucket](https://bitbucket.org/ariya/phantomjs/downloads) and copy them into the `.phantom` path. We're currently using 1.9.8, and you'll need the Window, Mac, and Linux builds. -<<<<<<< HEAD - -## Building and Packaging - -Make sure you have the dependencies installed by running `yarn kbn bootstrap`. - -Once complete, use `yarn build`. Output will be placed in the `build` path (it will be created). - -To drop the `SNAPSHOT` off the version, use the release flag, `-r` or `--release` - -If you'd like to get a zip package and a sha1 checksum file, use `yarn package`. Output will be placed in the `target` path (it will be created). Resulting build output will also be left in the `build` path. - -## Releasing - -Make sure you have the dependencies installed by running `yarn kbn bootstrap`. - -Once complete, use `yarn release`. Build and package output will be placed in the `build` and `target` paths respectively (they will be created). - -Note that you will need AWS credentials for the upload to succeed. To provide these credentials, create a `~/.aws/credentials` file with your credentials, which should look like this: - -``` -[default] ; the default profile -aws_access_key_id = ... -aws_secret_access_key = ... - -[another-config] ; my "personal-account" profile -aws_access_key_id = ... -aws_secret_access_key = ... -``` - -The `default` profile is used automatically, but setting the `AWS_PROFILE` environment variable will allow you to use another profile, if you happen to have multiple. - -`AWS_PROFILE=another-config yarn release` - -See [the AWS docs](http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html#Creating_the_Shared_Credentials_File) for more information. - -# Building documentation - -This repo contains X-Pack information that is used in the Kibana User Guide in 5.5 and later. - -To build the Kibana User Guide on your local machine, ensure you have the following folders: - -``` -$ ls $PATH_TO_REPOS - ├── kibana - └── kibana-extra/x-pack-kibana - -``` - -To build the Kibana User Guide, use the docbldkb or docbldkbx build commands defined in https://github.com/elastic/docs/blob/master/doc_build_aliases.sh -======= ->>>>>>> Updates to contributing guide and defaults (#13) diff --git a/x-pack/dev-tools/functional_tests/lib/auth.js b/x-pack/dev-tools/functional_tests/lib/auth.js deleted file mode 100644 index 8c456dd8c5985a..00000000000000 --- a/x-pack/dev-tools/functional_tests/lib/auth.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { format as formatUrl } from 'url'; - -import request from 'request'; -import { delay, fromNode as fcb } from 'bluebird'; - -export const DEFAULT_SUPERUSER_PASS = 'iamsuperuser'; - -async function updateCredentials(port, auth, username, password, retries = 10) { - const result = await fcb(cb => request({ - method: 'PUT', - uri: formatUrl({ - protocol: 'http:', - auth, - hostname: 'localhost', - port, - pathname: `/_xpack/security/user/${username}/_password`, - }), - json: true, - body: { password } - }, (err, httpResponse, body) => { - cb(err, { httpResponse, body }); - })); - - const { body, httpResponse } = result; - const { statusCode } = httpResponse; - if (statusCode === 200) { - return; - } - - if (retries > 0) { - await delay(2500); - return await updateCredentials(port, auth, username, password, retries - 1); - } - - throw new Error(`${statusCode} response, expected 200 -- ${JSON.stringify(body)}`); -} - -export async function setupUsers(log, ftrConfig) { - const esPort = ftrConfig.get('servers.elasticsearch.port'); - - // track the current credentials for the `elastic` user as - // they will likely change as we apply updates - let auth = 'elastic:iamsuperuser'; - - // list of updates we need to apply - const updates = [ - ftrConfig.get('servers.elasticsearch'), - ftrConfig.get('servers.kibana'), - ]; - - for (const { username, password } of updates) { - log.info('setting %j user password to %j', username, password); - await updateCredentials(esPort, auth, username, password); - if (username === 'elastic') { - auth = `elastic:${password}`; - } - } -} diff --git a/x-pack/dev-tools/functional_tests/lib/errors.js b/x-pack/dev-tools/functional_tests/lib/errors.js deleted file mode 100644 index 58ef32a94ee0ab..00000000000000 --- a/x-pack/dev-tools/functional_tests/lib/errors.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -const $isCliError = Symbol('isCliError'); - -export function createCliError(message) { - const error = new Error(message); - error[$isCliError] = true; - return error; -} - -export function isCliError(error) { - return error && !!error[$isCliError]; -} diff --git a/x-pack/dev-tools/functional_tests/lib/index.js b/x-pack/dev-tools/functional_tests/lib/index.js deleted file mode 100644 index 471e674446a3ca..00000000000000 --- a/x-pack/dev-tools/functional_tests/lib/index.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export { getFtrConfig } from './get_ftr_config'; - -export { runKibanaServer } from './run_kibana_server'; -export { runEsWithXpack } from './run_es_with_xpack'; -export { runFtr } from './run_ftr'; -export { log } from './log'; -export { KIBANA_FTR_SCRIPT } from './paths'; -export { isCliError } from './errors'; diff --git a/x-pack/dev-tools/functional_tests/lib/paths.js b/x-pack/dev-tools/functional_tests/lib/paths.js deleted file mode 100644 index e8d6a6bdff0600..00000000000000 --- a/x-pack/dev-tools/functional_tests/lib/paths.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { resolve } from 'path'; - -import { resolveKibanaPath } from '@kbn/plugin-helpers'; - -export const KIBANA_SCRIPT_PATH = resolveKibanaPath('scripts/kibana'); -export const KIBANA_ROOT = resolveKibanaPath(''); -export const XPACK_KIBANA_ROOT = resolve(KIBANA_ROOT, 'x-pack'); -export const GULP_COMMAND_PATH = resolve(XPACK_KIBANA_ROOT, 'node_modules/.bin/gulp'); -export const KIBANA_FTR_SCRIPT = resolve(KIBANA_ROOT, 'scripts/functional_test_runner'); -export const PROJECT_ROOT = resolve(__dirname, '../../../'); -export const FTR_CONFIG_PATH = resolve(PROJECT_ROOT, 'test/functional/config'); -export const OPTIMIZE_BUNDLE_DIR = resolve(KIBANA_ROOT, 'optimize/xpackTestUiServer'); diff --git a/x-pack/dev-tools/functional_tests/lib/run_es_with_xpack.js b/x-pack/dev-tools/functional_tests/lib/run_es_with_xpack.js deleted file mode 100644 index e2cefdbed853eb..00000000000000 --- a/x-pack/dev-tools/functional_tests/lib/run_es_with_xpack.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { resolve } from 'path'; -import { createTestCluster } from '../../../../src/test_utils/es/es_test_cluster'; -import { log } from './log'; - -import { setupUsers, DEFAULT_SUPERUSER_PASS } from './auth'; - -export async function runEsWithXpack({ ftrConfig, useSAML = false, from }) { - const cluster = createTestCluster({ - port: ftrConfig.get('servers.elasticsearch.port'), - password: DEFAULT_SUPERUSER_PASS, - license: 'trial', - from, - log, - }); - - const kibanaPort = ftrConfig.get('servers.kibana.port'); - const idpPath = resolve( - __dirname, - '../../../test/saml_api_integration/fixtures/idp_metadata.xml' - ); - - const esArgs = [ - 'xpack.security.enabled=true', - ]; - - const samlEsArgs = [ - ...esArgs, - 'xpack.security.authc.token.enabled=true', - 'xpack.security.authc.token.timeout=15s', - 'xpack.security.authc.realms.saml1.type=saml', - 'xpack.security.authc.realms.saml1.order=0', - `xpack.security.authc.realms.saml1.idp.metadata.path=${idpPath}`, - 'xpack.security.authc.realms.saml1.idp.entity_id=http://www.elastic.co', - `xpack.security.authc.realms.saml1.sp.entity_id=http://localhost:${kibanaPort}`, - `xpack.security.authc.realms.saml1.sp.logout=http://localhost:${kibanaPort}/logout`, - `xpack.security.authc.realms.saml1.sp.acs=http://localhost:${kibanaPort}/api/security/v1/saml`, - 'xpack.security.authc.realms.saml1.attributes.principal=urn:oid:0.0.7', - ]; - - await cluster.start(useSAML ? samlEsArgs : esArgs); - await setupUsers(log, ftrConfig); - - return cluster; -} diff --git a/x-pack/dev-tools/functional_tests/lib/run_ftr.js b/x-pack/dev-tools/functional_tests/lib/run_ftr.js deleted file mode 100644 index 530c75ba098c57..00000000000000 --- a/x-pack/dev-tools/functional_tests/lib/run_ftr.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - -import { - KIBANA_FTR_SCRIPT, - PROJECT_ROOT -} from './paths'; - -export async function runFtr({ procs, configPath, bail }) { - const args = [KIBANA_FTR_SCRIPT, '--debug']; - - if (configPath) { - args.push('--config', configPath); - } - - if (bail) { - args.push('--bail'); - } - - await procs.run('ftr', { - cmd: 'node', - args, - cwd: PROJECT_ROOT, - wait: true - }); -} diff --git a/x-pack/dev-tools/functional_tests/lib/run_kibana_server.js b/x-pack/dev-tools/functional_tests/lib/run_kibana_server.js deleted file mode 100644 index f0dd4bec86d653..00000000000000 --- a/x-pack/dev-tools/functional_tests/lib/run_kibana_server.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { resolve } from 'path'; -import { format as formatUrl } from 'url'; - -import { - KIBANA_ROOT, - KIBANA_SCRIPT_PATH, - OPTIMIZE_BUNDLE_DIR -} from './paths'; - -function getKibanaBin(installDir) { - return process.platform.startsWith('win') - ? resolve(installDir, 'bin/kibana.bat') - : resolve(installDir, 'bin/kibana'); -} - -export async function runKibanaServer(options) { - const { - procs, - ftrConfig, - devMode = false, - enableUI = true, - useSAML = false, - existingInstallDir = null, - } = options; - - if (devMode && existingInstallDir) { - throw new Error('Kibana installations can not be run in dev mode'); - } - - const runFromSourceArgs = existingInstallDir - ? ['--optimize.useBundleCache=true'] - : [ - KIBANA_SCRIPT_PATH, - '--no-base-path', - `--optimize.bundleDir=${OPTIMIZE_BUNDLE_DIR}`, - ]; - - const samlArgs = useSAML ? [ - '--server.xsrf.whitelist=[\"/api/security/v1/saml\"]', - '--xpack.security.authProviders=[\"saml\"]', - ] : []; - - // start the kibana server and wait for it to log "Server running" before resolving - await procs.run('kibana', { - cwd: existingInstallDir || KIBANA_ROOT, - - cmd: existingInstallDir - ? getKibanaBin(existingInstallDir) - : process.execPath, - - args: [ - ...runFromSourceArgs, - devMode ? '--dev' : '--env=development', - '--logging.json=false', - `--server.port=${ftrConfig.get('servers.kibana.port')}`, - `--server.uuid=${ftrConfig.get('env').kibana.server.uuid}`, - `--elasticsearch.url=${formatUrl(ftrConfig.get('servers.elasticsearch'))}`, - `--optimize.enabled=${enableUI}`, - `--optimize.watchPort=${ftrConfig.get('servers.kibana.port') + 1}`, - '--optimize.watchPrebuild=true', - '--status.allowAnonymous=true', - `--elasticsearch.username=${ftrConfig.get('servers.elasticsearch.username')}`, - `--elasticsearch.password=${ftrConfig.get('servers.elasticsearch.password')}`, - '--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"', // server restarts should not invalidate active sessions - '--xpack.monitoring.kibana.collection.enabled=false', - '--xpack.xpack_main.telemetry.enabled=false', - ...samlArgs, - ], - - env: { - FORCE_COLOR: 1, - ...process.env, - }, - - wait: /Server running/, - }); -} diff --git a/x-pack/dev-tools/functional_tests/tasks.js b/x-pack/dev-tools/functional_tests/tasks.js deleted file mode 100644 index 61129c0f451227..00000000000000 --- a/x-pack/dev-tools/functional_tests/tasks.js +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { relative } from 'path'; -import Rx from 'rxjs/Rx'; -import { Command } from 'commander'; -import { withProcRunner } from '@kbn/dev-utils'; - -import { - getFtrConfig, - runKibanaServer, - runEsWithXpack, - runFtr, - log, - KIBANA_FTR_SCRIPT, - isCliError, -} from './lib'; - -const SUCCESS_MESSAGE = ` - -Elasticsearch and Kibana are ready for functional testing. Start the functional tests -in another terminal session by running this command from this directory: - - node ${relative(process.cwd(), KIBANA_FTR_SCRIPT)} - -`; - -export function fatalErrorHandler(err) { - log.error('FATAL ERROR'); - log.error(isCliError(err) ? err.message : err); - process.exit(1); -} - -export async function runFunctionTests() { - const cmd = new Command('node scripts/functional_tests'); - - cmd - .option( - '--bail', - 'Stop the functional_test_runner as soon as a failure occurs' - ) - .option( - '--kibana-install-dir ', - 'Run Kibana from an existing install directory' - ) - .option( - '--es-from ', - 'Run ES from either source or snapshot [default: snapshot]' - ) - .parse(process.argv); - - await withProcRunner(async procs => { - const ftrConfig = await getFtrConfig(); - - const es = await runEsWithXpack({ ftrConfig, from: cmd.esFrom }); - await runKibanaServer({ - procs, - ftrConfig, - existingInstallDir: cmd.kibanaInstallDir, - }); - await runFtr({ - procs, - bail: cmd.bail, - }); - - await procs.stop('kibana'); - await es.cleanup(); - }); -} - -export async function runApiTests() { - const cmd = new Command('node scripts/functional_tests_api'); - - cmd - .option( - '--bail', - 'Stop the functional_test_runner as soon as a failure occurs' - ) - .option( - '--kibana-install-dir ', - 'Run Kibana from an existing install directory' - ) - .option( - '--es-from ', - 'Run ES from either source or snapshot [default: snapshot]' - ) - .parse(process.argv); - - try { - await withProcRunner(async procs => { - const ftrConfig = await getFtrConfig(); - - const es = await runEsWithXpack({ ftrConfig, from: cmd.esFrom }); - await runKibanaServer({ - procs, - ftrConfig, - enableUI: true, - existingInstallDir: cmd.kibanaInstallDir, - }); - await runFtr({ - procs, - configPath: require.resolve('../../test/api_integration/config.js'), - bail: cmd.bail, - }); - - await procs.stop('kibana'); - await es.cleanup(); - - // Run SAML specific API integration tests. - const samlEs = await runEsWithXpack({ - ftrConfig, - useSAML: true, - from: cmd.esFrom, - }); - await runKibanaServer({ - procs, - ftrConfig, - enableUI: false, - useSAML: true, - existingInstallDir: cmd.kibanaInstallDir, - }); - await runFtr({ - procs, - configPath: require.resolve( - '../../test/saml_api_integration/config.js' - ), - }); - - await procs.stop('kibana'); - await samlEs.cleanup(); - }); - } catch (err) { - fatalErrorHandler(err); - } -} - -export async function runFunctionalTestsServer() { - const cmd = new Command('node scripts/functional_test_server'); - - cmd - .option( - '--saml', - 'Run Elasticsearch and Kibana with configured SAML security realm', - false - ) - .option( - '--es-from ', - 'Run ES from either source or snapshot [default: snapshot]' - ) - .parse(process.argv); - - const useSAML = cmd.saml; - - try { - await withProcRunner(async procs => { - const ftrConfig = await getFtrConfig(); - await runEsWithXpack({ ftrConfig, useSAML, from: cmd.esFrom }); - await runKibanaServer({ - devMode: true, - procs, - ftrConfig, - useSAML, - }); - - // wait for 5 seconds of silence before logging the success message - // so that it doesn't get burried - await Rx.Observable.fromEvent(log, 'data') - .switchMap(() => Rx.Observable.timer(5000)) - .first() - .toPromise(); - - log.info(SUCCESS_MESSAGE); - await procs.waitForAllToStop(); - }); - } catch (err) { - fatalErrorHandler(err); - } -} diff --git a/x-pack/dev-tools/jest/create_jest_config.js b/x-pack/dev-tools/jest/create_jest_config.js index 071991781900d3..bbfaff767ecada 100644 --- a/x-pack/dev-tools/jest/create_jest_config.js +++ b/x-pack/dev-tools/jest/create_jest_config.js @@ -12,12 +12,16 @@ export function createJestConfig({ rootDir: xPackKibanaDirectory, roots: [ "/plugins", + "/server", ], moduleFileExtensions: [ "js", - "json" + "json", + "ts", + "tsx", ], moduleNameMapper: { + "^ui/(.*)": `${kibanaDirectory}/src/ui/public/$1`, "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": `${kibanaDirectory}/src/dev/jest/mocks/file_mock.js`, "\\.(css|less|scss)$": `${kibanaDirectory}/src/dev/jest/mocks/style_mock.js` @@ -27,10 +31,11 @@ export function createJestConfig({ `/dev-tools/jest/setup/enzyme.js` ], testMatch: [ - "**/*.test.js" + "**/*.test.{js,ts,tsx}" ], transform: { - "^.+\\.js$": `${kibanaDirectory}/src/dev/jest/babel_transform.js` + "^.+\\.js$": `${kibanaDirectory}/src/dev/jest/babel_transform.js`, + "^.+\\.tsx?$": `${kibanaDirectory}/src/dev/jest/ts_transform.js`, }, transformIgnorePatterns: [ "[/\\\\]node_modules[/\\\\].+\\.js$" diff --git a/x-pack/dev-tools/jest/index.js b/x-pack/dev-tools/jest/index.js index 3555dd8b288575..14c1b7ef42d2e4 100644 --- a/x-pack/dev-tools/jest/index.js +++ b/x-pack/dev-tools/jest/index.js @@ -6,7 +6,6 @@ import jest from 'jest'; import { resolve } from 'path'; -import { resolveKibanaPath } from '@kbn/plugin-helpers'; import { createJestConfig } from './create_jest_config'; @@ -14,8 +13,8 @@ import { createJestConfig } from './create_jest_config'; export function runJest() { process.env.NODE_ENV = process.env.NODE_ENV || 'test'; const config = JSON.stringify(createJestConfig({ - kibanaDirectory: resolveKibanaPath(''), - xPackKibanaDirectory: resolve(__dirname, '..', '..'), + kibanaDirectory: resolve(__dirname, '../../..'), + xPackKibanaDirectory: resolve(__dirname, '../..'), })); const argv = [ diff --git a/x-pack/docs/en/graph/release-notes.asciidoc b/x-pack/docs/en/graph/release-notes.asciidoc deleted file mode 100644 index f3055c4f235025..00000000000000 --- a/x-pack/docs/en/graph/release-notes.asciidoc +++ /dev/null @@ -1,66 +0,0 @@ -[[graph-release-notes]] -== Graph Release Notes (Pre-5.0) - -[float] -[[graph-change-list]] -=== Change List - -[float] -==== 2.4.2 -September 22, 2016 - -.Enhancements -* Adds support for Elasticsearch 2.4.2 - -[float] -==== 2.4.0 -August 31, 2016 - -.Enhancements -* Adds support for Elasticsearch 2.4.0 - - -[float] -==== 2.3.5 -August 3, 2016 - -.Enhancements -* Adds support for Elasticsearch 2.3.5 - -[float] -==== 2.3.4 -July 7, 2016 - -.Enhancements -* Adds support for Elasticsearch 2.3.4 - -[float] -==== 2.3.3 -May 18, 2016 - -.Enhancements -* Adds support for Elasticsearch 2.3.3 - -[float] -==== 2.3.2 -April 26, 2016 - -.Enhancements -* Adds support for Elasticsearch 2.3.2 - -[float] -==== 2.3.1 -April 4, 2016 - -.Enhancements -* Adds support for Elasticsearch 2.3.1 - -[float] -==== 2.3.0 -March 30, 2016 - -.New Features -* Introduces the <> and a Graph UI plugin for Kibana. - - - diff --git a/x-pack/docs/en/index.asciidoc b/x-pack/docs/en/index.asciidoc deleted file mode 100644 index 3b913c27b43796..00000000000000 --- a/x-pack/docs/en/index.asciidoc +++ /dev/null @@ -1,61 +0,0 @@ -:blog-ref: https://www.elastic.co/blog/ -:wikipedia: https://en.wikipedia.org/wiki - -include::{kib-repo-dir}/index-shared1.asciidoc[] - -:edit_url!: -include::setup/setup-xkb.asciidoc[] - -:edit_url: -include::{kib-repo-dir}/index-shared2.asciidoc[] - -:edit_url!: -include::release-notes/breaking-changes-xpack.asciidoc[] - -:edit_url: -include::{kib-repo-dir}/index-shared3.asciidoc[] - -:edit_url!: -include::ml/index.asciidoc[] - -:edit_url!:: -include::apm/index.asciidoc[] - -:edit_url!: -include::graph/index.asciidoc[] - -:edit_url: -include::{kib-repo-dir}/index-shared4.asciidoc[] - -:edit_url!: -include::searchprofiler/index.asciidoc[] - -:edit_url!: -include::grokdebugger/index.asciidoc[] - -:edit_url!: -include::monitoring/index.asciidoc[] - -:edit_url: -include::{kib-repo-dir}/index-shared5.asciidoc[] - -:edit_url!: -include::security/index.asciidoc[] - -:edit_url!: -include::management/watcher-ui/index.asciidoc[] - -:edit_url!: -include::upgrade-assistant/index.asciidoc[] - -:edit_url!: -include::dashboard_only_mode/index.asciidoc[] - -:edit_url!: -include::reporting/index.asciidoc[] - -:edit_url: -include::{kib-repo-dir}/index-shared6.asciidoc[] - -:edit_url!: -include::release-notes/index.asciidoc[] \ No newline at end of file diff --git a/x-pack/docs/en/monitoring/release-notes.asciidoc b/x-pack/docs/en/monitoring/release-notes.asciidoc deleted file mode 100644 index 3e964fba391e59..00000000000000 --- a/x-pack/docs/en/monitoring/release-notes.asciidoc +++ /dev/null @@ -1,168 +0,0 @@ -[[monitoring-release-notes]] -== Marvel Release Notes (Pre-5.0) - -This section summarizes the Monitoring changes in each release. -For information about upgrading X-Pack, see <>. - -[float] -[[monitoring-change-list]] -=== Change List - - -[float] -==== 2.4.2 -November 22, 2016 - -.Enhancements -* Compatibility with Elasticsearch 2.4.2. - -[float] -==== 2.4.0 -August 31, 2016 - -.Enhancements -* Node transport addresses are now consistently reported using only their IP address and port, rather than a subset reporting their resolved hostname, IP address, and port. - -.Bug Fixes -* Using the time picker to select clusters now honors the full time range, rather than only clusters that sent updates within the last 10 minutes. - - -[float] -==== 2.3.5 -August 3, 2016 - -.Bug Fixes -* Fixed sorting by number of unassigned shards in the indices table. -* Fixed the shard allocation tables to render when shards are relocating. -* Fixed the tooltips that are supposed to show for relocating shards in the -allocation table, and also added tooltips for shards of all states. -* Removed Google Analytics beacon, and fix the optional phone-home call to not -block page rendering. - -[float] -==== 2.3.4 -July 7, 2016 - -.Bug Fixes -* Using the time picker to select clusters now honors the full time range, -rather than only clusters that sent updates within the last 10 minutes. -* Phone home data omits `source_node` information that was being erroneously -picked up from the `cluster_info` field. -* Shards in the Relocating state are no longer counted as Unassigned Shards. -* Removed Google Analytics Tag from UI. -* The UI rendering no longer blocks waiting for the phone home call to return. -* Fixed the "no data" page to run an automatic refresh cycle to look for data. - -[float] -==== 2.3.3 -May 18, 2016 - -.Bug Fixes -* Prevents exceptions from being logged if the node stats are temporarily empty. - -[float] -==== 2.3.2 -April 26, 2016 - -.Bug Fixes -* Fixed a bug where non-elected master nodes all appeared as Offline in the node list. -+ -NOTE: You can workaround this in 2.3.0 and 2.3.1 by setting `marvel.node_resolver: name` in `kibana.yml`. -* Introduced the timepicker controls in the clusters page so you can view snapshots Marvel data. -* Added a link to go back to the previous page from the License page. - -[float] -==== 2.3.1 -April 4, 2016 - -.Enhancements -* Adds support for Elasticsearch 2.3.1 - -[float] -==== 2.3.0 -March 30, 2016 - -.Bug Fixes -* Minor UI improvements. - -.Enhancements -* Adds support for Elasticssearch 2.3.0 - -[float] -==== 2.2.1 -March 15, 2016 - -.Bug Fixes -* Fix a bug when Monitoring is configured to export data over HTTP on a monitoring cluster protected by Security (with SSL). - -[float] -==== 2.2.0 -February 2, 2016 - -.Enhancements -* Enable access to the License page from the cluster status bar. -* Allow configuration of a monthly interval for Monitoring indices instead of limiting it to daily. -* Provide a sha1 hash for the Monitoring app download. - -.Bug Fixes -* Minor UI improvements. - -[float] -==== 2.1.2 -February 2, 2016 - -.Enhancements -* Adds support for Elasticsearch 2.1.2 - -[float] -==== 2.1.1 -December 17, 2015 - -.Bug Fixes - -* Check the Kibana version to ensure compatibility. -* Respect opt-out for statistics reporting in all cases. -* Fixed transport address not showing on the node detail page. -* Fixed the table filtering on the node listing page. - -[float] -==== 2.1.0 -November 24, 2015 - -.Enhancements - -* Display a node type indicator on the Node Listing and Node Detail pages. -* Show the online/offline status of nodes. -* Remove the Time Picker from the Cluster Listing page. - -.Bug Fixes - -* Multiple fixes for showing historical data. -* Filter out derivative calculations where the start and end times are incomplete time buckets. -* Cluster table sorting. -* Use the new Elasticsearch `_field_stats` API to determine which Monitoring indices are needed to generate the stats. - -[float] -==== 2.0.1 -November 24, 2015 - -.Enhancements -* Adds support for Elasticsearch 2.0.1. - -[float] -==== 2.0.0 -October 28, 2015 - -.Breaking Changes - -Monitoring 2.0.0 is a complete rewrite from Monitoring 1.3. If you are upgrading from Monitoring 1.3, note that -the Monitoring agent plugin only needs to be installed on the Elasticsearch nodes you are monitoring. -If you need to stop collecting data from a node, remove the plugin or set the `xpack.monitoring.enabled` -configuration parameter to `false`. (The `xpack.monitoring.agent.enabled` parameter is no longer supported.) - -.New Features -* Fully-integrated with Kibana 4.2 as a Kibana plugin. -* Supports Multiple clusters for Paid Subscriptions -* Reduced data footprint for Monitoring indices -* Simplified dashboards for Indices and Nodes -* Better support for large clusters diff --git a/x-pack/docs/en/release-notes/7.0.0-alpha1.asciidoc b/x-pack/docs/en/release-notes/7.0.0-alpha1.asciidoc deleted file mode 100644 index 334532cbe36d4a..00000000000000 --- a/x-pack/docs/en/release-notes/7.0.0-alpha1.asciidoc +++ /dev/null @@ -1,23 +0,0 @@ -[role="xpack"] -[[xkb-7.0.0-alpha1]] -== 7.0.0-alpha1 - -[float] -[[xkb-breaking-7.0.0-alpha1]] -=== Breaking Changes - -No breaking changes have been made yet. -//// -[float] -[[features-7.0.0-alpha1]] -==== New Features - -[float] -[[enhancements-7.0.0-alpha1]] -==== Enhancements - -[float] -[[bugs-7.0.0-alpha1]] -==== Bug Fixes - -//// diff --git a/x-pack/docs/en/release-notes/breaking-changes-xpack.asciidoc b/x-pack/docs/en/release-notes/breaking-changes-xpack.asciidoc deleted file mode 100644 index ef686568850a8a..00000000000000 --- a/x-pack/docs/en/release-notes/breaking-changes-xpack.asciidoc +++ /dev/null @@ -1,22 +0,0 @@ -[role="xpack"] -[[breaking-changes-xkb]] -= {xpack} Breaking Changes - -[partintro] --- -This section summarizes the changes that you need to be aware of when migrating -your application from one version of {xpack} to another. - -* <> - -See also: - -* {ref}/breaking-changes-xes.html[{es} {xpack} Breaking Changes] -* {logstash-ref}/breaking-changes-xls.html[Logstash {xpack} Breaking Changes] --- - -[role="xpack"] -[[breaking-7.0.0-xkb]] -== {xpack} Breaking changes in 7.0.0 - -No breaking changes have been made yet. diff --git a/x-pack/docs/en/release-notes/index.asciidoc b/x-pack/docs/en/release-notes/index.asciidoc deleted file mode 100644 index 100dae3a05c231..00000000000000 --- a/x-pack/docs/en/release-notes/index.asciidoc +++ /dev/null @@ -1,21 +0,0 @@ -[role="xpack"] -[[release-notes-xkb]] -= {xpack} Release Notes - -[partintro] --- -This section summarizes the changes in each release for all of the {xpack} -components in {kib}: {security}, {monitoring}, {watcher}, {reporting}, {xpackml}, -and {graph}. - -* <> - -See also: - -* <> -* {ref}/es-release-notes.html[{es} {xpack} Release Notes] -* {logstash-ref}/release-notes-xls.html[Logstash {xpack} Release Notes] - --- - -include::7.0.0-alpha1.asciidoc[] diff --git a/x-pack/docs/en/reporting/release-notes.asciidoc b/x-pack/docs/en/reporting/release-notes.asciidoc deleted file mode 100644 index dcfffeeba33acb..00000000000000 --- a/x-pack/docs/en/reporting/release-notes.asciidoc +++ /dev/null @@ -1,14 +0,0 @@ -[[reporting-release-notes]] -== Reporting Release Notes (Pre-5.0) - -[float] -[[reporting-change-list]] -=== Change List - -[float] -==== 2.4.0 -August 31, 2016 - -.New Features - -* Manually Export PDF reports from Kibana and automatically generate reports from Watcher. \ No newline at end of file diff --git a/x-pack/docs/en/setup/images/KibanaFlow.jpg b/x-pack/docs/en/setup/images/KibanaFlow.jpg deleted file mode 100644 index 6d8bab6bc090e6..00000000000000 Binary files a/x-pack/docs/en/setup/images/KibanaFlow.jpg and /dev/null differ diff --git a/x-pack/gulp_helpers/get_plugins.js b/x-pack/gulp_helpers/get_plugins.js index 1805fd2d999f17..ead832ca756b4b 100644 --- a/x-pack/gulp_helpers/get_plugins.js +++ b/x-pack/gulp_helpers/get_plugins.js @@ -7,8 +7,7 @@ const path = require('path'); const yargs = require('yargs'); const glob = require('glob'); -const { resolveKibanaPath } = require('@kbn/plugin-helpers'); -const { findPluginSpecs } = require(resolveKibanaPath('src/plugin_discovery')); +const { findPluginSpecs } = require('../../src/plugin_discovery'); /* Usage: diff --git a/x-pack/index.js b/x-pack/index.js index ba26c8fcf41610..f20e87de989845 100644 --- a/x-pack/index.js +++ b/x-pack/index.js @@ -21,6 +21,7 @@ import { licenseManagement } from './plugins/license_management'; import { cloud } from './plugins/cloud'; import { indexManagement } from './plugins/index_management'; import { consoleExtensions } from './plugins/console_extensions'; +import { notifications } from './plugins/notifications'; module.exports = function (kibana) { return [ @@ -40,6 +41,7 @@ module.exports = function (kibana) { licenseManagement(kibana), cloud(kibana), indexManagement(kibana), - consoleExtensions(kibana) + consoleExtensions(kibana), + notifications(kibana), ]; }; diff --git a/x-pack/package.json b/x-pack/package.json index 645ad7bdee552c..936d446f1b14cd 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -24,7 +24,9 @@ }, "devDependencies": { "@kbn/dev-utils": "link:../packages/kbn-dev-utils", + "@kbn/es": "link:../packages/kbn-es", "@kbn/plugin-helpers": "link:../packages/kbn-plugin-helpers", + "@kbn/test": "link:../packages/kbn-test", "@types/jest": "^22.2.3", "abab": "^1.0.4", "ansicolors": "0.3.2", @@ -38,10 +40,9 @@ "del": "2.2.0", "dotenv": "2.0.0", "enzyme": "3.2.0", - "enzyme-adapter-react-16": "^1.1.0", + "enzyme-adapter-react-16": "^1.1.1", "enzyme-to-json": "3.3.1", "expect.js": "0.3.1", - "fetch-mock": "5.13.1", "gulp": "3.9.1", "gulp-load-plugins": "1.2.0", "gulp-mocha": "2.2.0", @@ -52,7 +53,8 @@ "jest": "^22.4.3", "jest-cli": "^22.4.3", "jest-styled-components": "^5.0.1", - "mocha": "^5.0.5", + "mocha": "3.3.0", + "mustache": "^2.3.0", "node-fetch": "^2.1.2", "pdf-image": "1.1.0", "pixelmatch": "4.0.2", @@ -61,25 +63,26 @@ "redux-test-utils": "0.2.2", "rsync": "0.4.0", "run-sequence": "^2.2.1", - "simple-git": "1.32.1", - "sinon": "1.17.3", - "sinon-as-promised": "4.0.3", + "simple-git": "1.37.0", + "sinon": "^5.0.7", "supertest": "3.0.0", "supertest-as-promised": "4.0.2", "tmp": "0.0.31", "tree-kill": "^1.1.0", - "vinyl-fs": "2.3.1", + "typescript": "^2.8.3", + "vinyl-fs": "^3.0.2", "xml-crypto": "^0.10.1", "xml2js": "^0.4.19", "yargs": "4.7.1" }, "dependencies": { - "@elastic/eui": "0.0.38", + "@elastic/eui": "0.0.49", "@elastic/node-crypto": "0.1.2", "@elastic/node-phantom-simple": "2.2.4", "@elastic/numeral": "2.3.2", "@kbn/datemath": "link:../packages/kbn-datemath", "@kbn/ui-framework": "link:../packages/kbn-ui-framework", + "@slack/client": "^4.2.2", "angular-paging": "2.2.1", "angular-resource": "1.4.9", "angular-sanitize": "1.4.9", @@ -120,6 +123,7 @@ "moment-duration-format": "^1.3.0", "moment-timezone": "^0.5.14", "ngreact": "^0.5.1", + "nodemailer": "^4.6.4", "object-hash": "1.2.0", "path-match": "1.2.4", "pdfmake": "0.1.33", @@ -128,12 +132,13 @@ "pngjs": "3.3.1", "prop-types": "^15.6.0", "puid": "1.0.5", - "react": "^16.2.0", + "react": "^16.3.0", "react-clipboard.js": "^1.1.2", - "react-dom": "^16.2.0", + "react-dom": "^16.3.0", "react-markdown-renderer": "^1.4.0", "react-portal": "^3.2.0", "react-redux": "^5.0.5", + "react-redux-request": "^1.5.5", "react-router-breadcrumbs-hoc": "1.1.2", "react-router-dom": "^4.2.2", "react-select": "^1.2.1", diff --git a/x-pack/scripts/functional_tests_api.js b/x-pack/plugins/__mocks__/ui/kfetch.js similarity index 70% rename from x-pack/scripts/functional_tests_api.js rename to x-pack/plugins/__mocks__/ui/kfetch.js index f6aab24238c9d3..84b1c609ed6458 100644 --- a/x-pack/scripts/functional_tests_api.js +++ b/x-pack/plugins/__mocks__/ui/kfetch.js @@ -4,5 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -require('@kbn/plugin-helpers').babelRegister(); -require('../dev-tools/functional_tests').runApiTests(); +export const kfetch = () => { + return Promise.resolve('mock value'); +}; diff --git a/x-pack/plugins/apm/server/lib/helpers/date_validation.js b/x-pack/plugins/__mocks__/ui/kuery.js similarity index 65% rename from x-pack/plugins/apm/server/lib/helpers/date_validation.js rename to x-pack/plugins/__mocks__/ui/kuery.js index d4531a2bca4eab..294a9f34bce75b 100644 --- a/x-pack/plugins/apm/server/lib/helpers/date_validation.js +++ b/x-pack/plugins/__mocks__/ui/kuery.js @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import Joi from 'joi'; -export const dateValidation = Joi.alternatives() - .try(Joi.date().iso(), Joi.number()) - .required(); +export function fromKueryExpression() {} +export function toElasticsearchQuery() {} +export function getSuggestionsProvider() {} diff --git a/x-pack/dev-tools/functional_tests/lib/log.js b/x-pack/plugins/__mocks__/ui/metadata.js similarity index 66% rename from x-pack/dev-tools/functional_tests/lib/log.js rename to x-pack/plugins/__mocks__/ui/metadata.js index 09978075637919..0aca5da8de5453 100644 --- a/x-pack/dev-tools/functional_tests/lib/log.js +++ b/x-pack/plugins/__mocks__/ui/metadata.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createToolingLog } from '@kbn/dev-utils'; - -export const log = createToolingLog('debug'); -log.pipe(process.stdout); +export const metadata = { + branch: 'my-metadata-branch', + version: 'my-metadata-version' +}; diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/index.js b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/index.js index 4f0a78b204aa2b..cf6b8f78834496 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/index.js +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/index.js @@ -4,22 +4,50 @@ * you may not use this file except in compliance with the Elastic License. */ -import { connect } from 'react-redux'; -import Distribution from './view'; -import { getUrlParams } from '../../../../store/urlParams'; -import { - loadErrorDistribution, - getErrorDistribution -} from '../../../../store/errorDistribution'; - -function mapStateToProps(state = {}) { - return { - urlParams: getUrlParams(state), - distribution: getErrorDistribution(state) - }; +import React from 'react'; +import Histogram from '../../../shared/charts/Histogram'; +import EmptyMessage from '../../../shared/EmptyMessage'; +import { HeaderSmall } from '../../../shared/UIComponents'; + +export function getFormattedBuckets(buckets, bucketSize) { + if (!buckets) { + return null; + } + + return buckets.map(({ count, key }) => { + return { + x0: key, + x: key + bucketSize, + y: count + }; + }); +} + +function Distribution({ distribution }) { + const buckets = getFormattedBuckets( + distribution.buckets, + distribution.bucketSize + ); + + const isEmpty = distribution.totalHits === 0; + + if (isEmpty) { + return ; + } + + return ( +
+ Occurrences + bucket.x} + xType="time" + buckets={buckets} + bucketSize={distribution.bucketSize} + formatYShort={value => `${value} occ.`} + formatYLong={value => `${value} occurrences`} + /> +
+ ); } -const mapDispatchToProps = { - loadErrorDistribution -}; -export default connect(mapStateToProps, mapDispatchToProps)(Distribution); +export default Distribution; diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/view.js b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/view.js deleted file mode 100644 index bd9c2cf2151764..00000000000000 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution/view.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component } from 'react'; -import Histogram from '../../../shared/charts/Histogram'; -import EmptyMessage from '../../../shared/EmptyMessage'; -import { HeaderSmall } from '../../../shared/UIComponents'; -import { getKey } from '../../../../store/apiHelpers'; - -export function getFormattedBuckets(buckets, bucketSize) { - if (!buckets) { - return null; - } - - return buckets.map(({ count, key }) => { - return { - x0: key, - x: key + bucketSize, - y: count - }; - }); -} - -function maybeLoadErrorDistribution(props) { - const { serviceName, start, end, errorGroupId } = props.urlParams; - const keyArgs = { serviceName, start, end, errorGroupId }; - const key = getKey(keyArgs); - - //TODO what about load status? `props.distribution.status` - if (key && props.distribution.key !== key) { - props.loadErrorDistribution(keyArgs); - } -} - -class Distribution extends Component { - componentDidMount() { - maybeLoadErrorDistribution(this.props); - } - - componentWillReceiveProps(nextProps) { - maybeLoadErrorDistribution(nextProps); - } - - render() { - const { distribution } = this.props; - const buckets = getFormattedBuckets( - distribution.data.buckets, - distribution.data.bucketSize - ); - - const isEmpty = distribution.data.totalHits === 0; - - if (isEmpty) { - return ; - } - - return ( -
- Occurrences - bucket.x} - xType="time" - buckets={buckets} - bucketSize={distribution.data.bucketSize} - formatYShort={value => `${value} occ.`} - formatYLong={value => `${value} occurrences`} - /> -
- ); - } -} - -export default Distribution; diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/index.js b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/index.js index a328b4b9c76c14..cef63c61b047bb 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/index.js +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/index.js @@ -7,18 +7,14 @@ import { connect } from 'react-redux'; import ErrorGroupDetails from './view'; import { getUrlParams } from '../../../store/urlParams'; -import { getErrorGroup, loadErrorGroup } from '../../../store/errorGroup'; function mapStateToProps(state = {}) { return { urlParams: getUrlParams(state), - errorGroup: getErrorGroup(state), location: state.location }; } -const mapDispatchToProps = { - loadErrorGroup -}; +const mapDispatchToProps = {}; export default connect(mapStateToProps, mapDispatchToProps)(ErrorGroupDetails); diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/view.js b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/view.js index 173b698fbfc94f..f346c0ea1ae02a 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/view.js +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/view.js @@ -4,11 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, Component } from 'react'; +import React, { Fragment } from 'react'; import styled from 'styled-components'; import PropTypes from 'prop-types'; import { get } from 'lodash'; -import withErrorHandler from '../../shared/withErrorHandler'; import { HeaderLarge } from '../../shared/UIComponents'; import DetailView from './DetailView'; import Distribution from './Distribution'; @@ -28,7 +27,8 @@ import { ERROR_EXC_MESSAGE, ERROR_EXC_HANDLED } from '../../../../common/constants'; -import { getKey } from '../../../store/apiHelpers'; +import { ErrorDistributionRequest } from '../../../store/reactReduxRequest/errorDistribution'; +import { ErrorGroupDetailsRequest } from '../../../store/reactReduxRequest/errorGroup'; const Titles = styled.div` margin-bottom: ${px(units.plus)}; @@ -56,14 +56,6 @@ const Culprit = styled.div` font-family: ${fontFamilyCode}; `; -function loadErrorGroup(props) { - const { serviceName, errorGroupId, start, end } = props.urlParams; - const key = getKey({ serviceName, errorGroupId, start, end }); - if (key && props.errorGroup.key !== key) { - props.loadErrorGroup({ serviceName, errorGroupId, start, end }); - } -} - function getShortGroupId(errorGroupId) { if (!errorGroupId) { return 'N/A'; @@ -72,65 +64,64 @@ function getShortGroupId(errorGroupId) { return errorGroupId.slice(0, 5); } -class ErrorGroupDetails extends Component { - componentDidMount() { - loadErrorGroup(this.props); - } - - componentWillReceiveProps(nextProps) { - loadErrorGroup(nextProps); - } - - render() { - const { errorGroup, urlParams, location } = this.props; - - // If there are 0 occurrences, show only distribution chart w. empty message - const showDetails = errorGroup.data.occurrencesCount !== 0; - const logMessage = get(errorGroup.data.error, ERROR_LOG_MESSAGE); - const excMessage = get(errorGroup.data.error, ERROR_EXC_MESSAGE); - const culprit = get(errorGroup.data.error, ERROR_CULPRIT); - const isUnhandled = get(errorGroup.data.error, ERROR_EXC_HANDLED) === false; - - return ( -
- - Error group {getShortGroupId(urlParams.errorGroupId)} - {isUnhandled && ( - Unhandled - )} - - - {showDetails && ( - - - {logMessage && ( - - - {logMessage} - +function ErrorGroupDetails({ urlParams, location }) { + return ( + { + // If there are 0 occurrences, show only distribution chart w. empty message + const showDetails = errorGroup.data.occurrencesCount !== 0; + const logMessage = get(errorGroup.data.error, ERROR_LOG_MESSAGE); + const excMessage = get(errorGroup.data.error, ERROR_EXC_MESSAGE); + const culprit = get(errorGroup.data.error, ERROR_CULPRIT); + const isUnhandled = + get(errorGroup.data.error, ERROR_EXC_HANDLED) === false; + + return ( +
+ + Error group {getShortGroupId(urlParams.errorGroupId)} + {isUnhandled && ( + Unhandled )} - - {excMessage || 'N/A'} - - {culprit || 'N/A'} - - - )} - - {showDetails && ( - - )} -
- ); - } + + + {showDetails && ( + + + {logMessage && ( + + + {logMessage} + + )} + + {excMessage || 'N/A'} + + {culprit || 'N/A'} + + + )} + } + /> + {showDetails && ( + + )} +
+ ); + }} + /> + ); } ErrorGroupDetails.propTypes = { location: PropTypes.object.isRequired }; -export default withErrorHandler(ErrorGroupDetails, ['errorGroup']); +export default ErrorGroupDetails; diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/ListItem.js b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/ListItem.js index 04833126fa1957..069823906535cc 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/ListItem.js +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/ListItem.js @@ -73,13 +73,13 @@ function ListItem({ error, serviceName }) { return ( - + {groupId.slice(0, 5) || 'N/A'} - + {message || 'N/A'} diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.js b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.js index 3c349638439269..b4ab336f378b75 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.js +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.js @@ -25,7 +25,7 @@ describe('ErrorGroupOverview -> List', () => { const storeState = {}; const wrapper = mount( - + , storeState ); diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.js.snap b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.js.snap index e81d486b06966b..f7c76ba0072bbe 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.js.snap +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.js.snap @@ -111,7 +111,7 @@ exports[`ErrorGroupOverview -> List should render empty state 1`] = ` Oops! You should try another time range. If that's no good, there's always the diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/WatcherFlyOut.js b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/WatcherFlyOut.js index 5463eb892f7c89..54c6f0a8e03220 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/WatcherFlyOut.js +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/WatcherFlyOut.js @@ -149,8 +149,14 @@ export default class WatcherFlyout extends Component { const timeRange = this.state.schedule === 'interval' - ? `now-${this.state.interval.value}${this.state.interval.unit}` - : 'now-24h'; + ? { + value: this.state.interval.value, + unit: this.state.interval.unit + } + : { + value: 24, + unit: 'h' + }; return createErrorGroupWatch({ emails, @@ -255,6 +261,7 @@ export default class WatcherFlyout extends Component { - + - + + + @@ -348,6 +361,7 @@ export default class WatcherFlyout extends Component { {this.state.actions.email && ( If you have not configured email, please see the{' '} @@ -378,6 +392,7 @@ export default class WatcherFlyout extends Component { {this.state.actions.slack && ( To get a Slack webhook, please see the{' '} @@ -438,7 +453,7 @@ export default class WatcherFlyout extends Component { return ( - {this.props.isFlyoutOpen && flyout} + {this.props.isOpen && flyout} this is a string +N/A +7761 occurrences + +foo + (server/coffee.js) +7752 occurrences + +socket hang up +createHangUpError (_http_client.js) +3887 occurrences + +this will not get captured by express + (server/coffee.js) +3886 occurrences +" +`; + +exports[`createErrorGroupWatch should format entire template correctly 1`] = ` Object { "actions": Object { "email": Object { "email": Object { "body": Object { - "html": "Your service \\"{{ctx.metadata.serviceName}}\\" has error groups which exceeds {{ctx.metadata.threshold}} occurrences within \\"{{ctx.metadata.timeRangeHumanReadable}}\\"

{{#ctx.payload.aggregations.error_groups.buckets}}
{{sample.hits.hits.0._source.error.log.message}}{{^sample.hits.hits.0._source.error.log.message}}{{sample.hits.hits.0._source.error.exception.message}}{{/sample.hits.hits.0._source.error.log.message}}
{{sample.hits.hits.0._source.error.culprit}}{{^sample.hits.hits.0._source.error.culprit}}N/A{{/sample.hits.hits.0._source.error.culprit}}
{{doc_count}} occurrences
{{/ctx.payload.aggregations.error_groups.buckets}}", + "html": "Your service \\"opbeans-node\\" has error groups which exceeds 10 occurrences within \\"24h\\"


this is a string
N/A
7761 occurrences

foo
(server/coffee.js)
7752 occurrences

socket hang up
createHangUpError (_http_client.js)
3887 occurrences

this will not get captured by express
(server/coffee.js)
3886 occurrences
", }, - "subject": "\\"{{ctx.metadata.serviceName}}\\" has error groups which exceeds the threshold", - "to": "{{ctx.metadata.emails}}", + "subject": "\\"opbeans-node\\" has error groups which exceeds the threshold", + "to": "my@email.dk,mySecond@email.dk", }, }, "log_error": Object { "logging": Object { - "text": "Your service \\"{{ctx.metadata.serviceName}}\\" has error groups which exceeds {{ctx.metadata.threshold}} occurrences within \\"{{ctx.metadata.timeRangeHumanReadable}}\\"

{{#ctx.payload.aggregations.error_groups.buckets}}
{{sample.hits.hits.0._source.error.log.message}}{{^sample.hits.hits.0._source.error.log.message}}{{sample.hits.hits.0._source.error.exception.message}}{{/sample.hits.hits.0._source.error.log.message}}
{{sample.hits.hits.0._source.error.culprit}}{{^sample.hits.hits.0._source.error.culprit}}N/A{{/sample.hits.hits.0._source.error.culprit}}
{{doc_count}} occurrences
{{/ctx.payload.aggregations.error_groups.buckets}}", + "text": "Your service \\"opbeans-node\\" has error groups which exceeds 10 occurrences within \\"24h\\"


this is a string
N/A
7761 occurrences

foo
(server/coffee.js)
7752 occurrences

socket hang up
createHangUpError (_http_client.js)
3887 occurrences

this will not get captured by express
(server/coffee.js)
3886 occurrences
", }, }, "slack_webhook": Object { "webhook": Object { - "body": "{\\"text\\":\\"Your service \\\\\\"{{ctx.metadata.serviceName}}\\\\\\" has error groups which exceeds {{ctx.metadata.threshold}} occurrences within \\\\\\"{{ctx.metadata.timeRangeHumanReadable}}\\\\\\"\\\\n{{#ctx.payload.aggregations.error_groups.buckets}}\\\\n>*{{sample.hits.hits.0._source.error.log.message}}{{^sample.hits.hits.0._source.error.log.message}}{{sample.hits.hits.0._source.error.exception.message}}{{/sample.hits.hits.0._source.error.log.message}}*\\\\n>{{#sample.hits.hits.0._source.error.culprit}}\`{{sample.hits.hits.0._source.error.culprit}}\`{{/sample.hits.hits.0._source.error.culprit}}{{^sample.hits.hits.0._source.error.culprit}}N/A{{/sample.hits.hits.0._source.error.culprit}}\\\\n>{{doc_count}} occurrences\\\\n{{/ctx.payload.aggregations.error_groups.buckets}}\\"}", + "body": "{\\"text\\":\\"Your service \\\\\\"opbeans-node\\\\\\" has error groups which exceeds 10 occurrences within \\\\\\"24h\\\\\\"\\\\n\\\\n>*this is a string*\\\\n>N/A\\\\n>7761 occurrences\\\\n\\\\n>*foo*\\\\n>\` (server/coffee.js)\`\\\\n>7752 occurrences\\\\n\\\\n>*socket hang up*\\\\n>\`createHangUpError (_http_client.js)\`\\\\n>3887 occurrences\\\\n\\\\n>*this will not get captured by express*\\\\n>\` (server/coffee.js)\`\\\\n>3886 occurrences\\\\n\\"}", "headers": Object { "Content-Type": "application/json", }, "host": "hooks.slack.com", "method": "POST", - "path": "{{ctx.metadata.slackUrlPath}}", + "path": "/services/slackid1/slackid2/slackid3", "port": 443, "scheme": "https", }, @@ -64,7 +86,7 @@ Object { }, "terms": Object { "field": "error.grouping_key", - "min_doc_count": "{{ctx.metadata.threshold}}", + "min_doc_count": "10", "order": Object { "_count": "desc", }, @@ -77,7 +99,7 @@ Object { "filter": Array [ Object { "term": Object { - "context.service.name": "{{ctx.metadata.serviceName}}", + "context.service.name": "opbeans-node", }, }, Object { @@ -88,7 +110,7 @@ Object { Object { "range": Object { "@timestamp": Object { - "gte": "{{ctx.metadata.timeRange}}", + "gte": "now-24h", }, }, }, @@ -106,12 +128,13 @@ Object { "metadata": Object { "emails": Array [ "my@email.dk", + "mySecond@email.dk", ], "serviceName": "opbeans-node", "slackUrlPath": "/services/slackid1/slackid2/slackid3", "threshold": 10, - "timeRange": "now-24h", - "timeRangeHumanReadable": "24h", + "timeRangeUnit": "h", + "timeRangeValue": 24, "trigger": "This value must be changed in trigger section", }, "trigger": Object { @@ -125,10 +148,22 @@ Object { `; exports[`createErrorGroupWatch should format slack message correctly 1`] = ` -"Your service \\"{{ctx.metadata.serviceName}}\\" has error groups which exceeds {{ctx.metadata.threshold}} occurrences within \\"{{ctx.metadata.timeRangeHumanReadable}}\\" -{{#ctx.payload.aggregations.error_groups.buckets}} ->*{{sample.hits.hits.0._source.error.log.message}}{{^sample.hits.hits.0._source.error.log.message}}{{sample.hits.hits.0._source.error.exception.message}}{{/sample.hits.hits.0._source.error.log.message}}* ->{{#sample.hits.hits.0._source.error.culprit}}\`{{sample.hits.hits.0._source.error.culprit}}\`{{/sample.hits.hits.0._source.error.culprit}}{{^sample.hits.hits.0._source.error.culprit}}N/A{{/sample.hits.hits.0._source.error.culprit}} ->{{doc_count}} occurrences -{{/ctx.payload.aggregations.error_groups.buckets}}" +"Your service \\"opbeans-node\\" has error groups which exceeds 10 occurrences within \\"24h\\" + +>*this is a string* +>N/A +>7761 occurrences + +>*foo* +>\` (server/coffee.js)\` +>7752 occurrences + +>*socket hang up* +>\`createHangUpError (_http_client.js)\` +>3887 occurrences + +>*this will not get captured by express* +>\` (server/coffee.js)\` +>3886 occurrences +" `; diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/__test__/createErrorGroupWatch.test.js b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/__test__/createErrorGroupWatch.test.js index 8cfecbf0d98850..baf0795a0d6c44 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/__test__/createErrorGroupWatch.test.js +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/__test__/createErrorGroupWatch.test.js @@ -5,17 +5,28 @@ */ import { createErrorGroupWatch } from '../createErrorGroupWatch'; +import mustache from 'mustache'; import chrome from 'ui/chrome'; import * as rest from '../../../../../services/rest'; +import { isObject, isArray, isString } from 'lodash'; +import esResponse from './esResponse.json'; + +jest.mock('uuid', () => ({ + v4: jest.fn(() => 'mocked-uuid') +})); + +// disable html escaping since this is also disabled in watcher\s mustache implementation +mustache.escape = value => value; describe('createErrorGroupWatch', () => { - let res; + let createWatchResponse; + let tmpl; beforeEach(async () => { chrome.getInjected = jest.fn().mockReturnValue('myIndexPattern'); jest.spyOn(rest, 'createWatch').mockReturnValue(); - res = await createErrorGroupWatch({ - emails: ['my@email.dk'], + createWatchResponse = await createErrorGroupWatch({ + emails: ['my@email.dk', 'mySecond@email.dk'], schedule: { daily: { at: '08:00' @@ -24,27 +35,75 @@ describe('createErrorGroupWatch', () => { serviceName: 'opbeans-node', slackUrl: 'https://hooks.slack.com/services/slackid1/slackid2/slackid3', threshold: 10, - timeRange: 'now-24h' + timeRange: { value: 24, unit: 'h' } }); + + const watchBody = rest.createWatch.mock.calls[0][1]; + const templateCtx = { + payload: esResponse, + metadata: watchBody.metadata + }; + + tmpl = renderMustache(rest.createWatch.mock.calls[0][1], templateCtx); }); afterEach(() => jest.restoreAllMocks()); it('should call createWatch with correct args', () => { - expect(rest.createWatch.mock.calls[0][0]).toContain('apm-'); - expect(rest.createWatch.mock.calls[0][1]).toMatchSnapshot(); + expect(rest.createWatch.mock.calls[0][0]).toBe('apm-mocked-uuid'); }); it('should format slack message correctly', () => { + expect(tmpl.actions.slack_webhook.webhook.path).toBe( + '/services/slackid1/slackid2/slackid3' + ); + expect( + JSON.parse(tmpl.actions.slack_webhook.webhook.body).text + ).toMatchSnapshot(); + }); + + it('should format email correctly', () => { + expect(tmpl.actions.email.email.to).toEqual( + 'my@email.dk,mySecond@email.dk' + ); + expect(tmpl.actions.email.email.subject).toBe( + '"opbeans-node" has error groups which exceeds the threshold' + ); expect( - JSON.parse( - rest.createWatch.mock.calls[0][1].actions.slack_webhook.webhook.body - ).text + tmpl.actions.email.email.body.html.replace(//g, '\n') ).toMatchSnapshot(); }); + it('should format entire template correctly', () => { + expect(tmpl).toMatchSnapshot(); + }); + it('should return watch id', async () => { const id = rest.createWatch.mock.calls[0][0]; - expect(res).toEqual(id); + expect(createWatchResponse).toEqual(id); }); }); + +// Recusively iterate a nested structure and render strings as mustache templates +function renderMustache(input, ctx) { + if (isString(input)) { + return mustache.render(input, { + ctx, + join: () => (text, render) => render(`{{${text}}}`, { ctx }) + }); + } + + if (isArray(input)) { + return input.map(itemValue => renderMustache(itemValue, ctx)); + } + + if (isObject(input)) { + return Object.keys(input).reduce((acc, key) => { + const value = input[key]; + + return { ...acc, [key]: renderMustache(value, ctx) }; + }, {}); + } + + return input; +} diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/__test__/esResponse.json b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/__test__/esResponse.json new file mode 100644 index 00000000000000..b2aa6c545b163a --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/__test__/esResponse.json @@ -0,0 +1,141 @@ +{ + "took": 454, + "timed_out": false, + "_shards": { + "total": 10, + "successful": 10, + "skipped": 0, + "failed": 0 + }, + "hits": { + "total": 23287, + "max_score": 0, + "hits": [] + }, + "aggregations": { + "error_groups": { + "doc_count_error_upper_bound": 0, + "sum_other_doc_count": 0, + "buckets": [ + { + "key": "63925d00b445cdf4b532dd09d185f5c6", + "doc_count": 7761, + "sample": { + "hits": { + "total": 7761, + "max_score": null, + "hits": [ + { + "_index": "apm-7.0.0-alpha1-error-2018.04.25", + "_type": "doc", + "_id": "qH7C_WIBcmGuKeCHJvvT", + "_score": null, + "_source": { + "@timestamp": "2018-04-25T17:03:02.296Z", + "error": { + "log": { + "message": "this is a string" + }, + "grouping_key": "63925d00b445cdf4b532dd09d185f5c6" + } + }, + "sort": [1524675782296] + } + ] + } + } + }, + { + "key": "89bb1a1f644c7f4bbe8d1781b5cb5fd5", + "doc_count": 7752, + "sample": { + "hits": { + "total": 7752, + "max_score": null, + "hits": [ + { + "_index": "apm-7.0.0-alpha1-error-2018.04.25", + "_type": "doc", + "_id": "_3_D_WIBcmGuKeCHFwOW", + "_score": null, + "_source": { + "@timestamp": "2018-04-25T17:04:03.504Z", + "error": { + "exception": { + "handled": true, + "message": "foo" + }, + "culprit": " (server/coffee.js)", + "grouping_key": "89bb1a1f644c7f4bbe8d1781b5cb5fd5" + } + }, + "sort": [1524675843504] + } + ] + } + } + }, + { + "key": "7a17ea60604e3531bd8de58645b8631f", + "doc_count": 3887, + "sample": { + "hits": { + "total": 3887, + "max_score": null, + "hits": [ + { + "_index": "apm-7.0.0-alpha1-error-2018.04.25", + "_type": "doc", + "_id": "dn_D_WIBcmGuKeCHQgXJ", + "_score": null, + "_source": { + "@timestamp": "2018-04-25T17:04:14.575Z", + "error": { + "exception": { + "handled": false, + "message": "socket hang up" + }, + "culprit": "createHangUpError (_http_client.js)", + "grouping_key": "7a17ea60604e3531bd8de58645b8631f" + } + }, + "sort": [1524675854575] + } + ] + } + } + }, + { + "key": "b9e1027f29c221763f864f6fa2ad9f5e", + "doc_count": 3886, + "sample": { + "hits": { + "total": 3886, + "max_score": null, + "hits": [ + { + "_index": "apm-7.0.0-alpha1-error-2018.04.25", + "_type": "doc", + "_id": "dX_D_WIBcmGuKeCHQgXJ", + "_score": null, + "_source": { + "@timestamp": "2018-04-25T17:04:14.533Z", + "error": { + "exception": { + "handled": false, + "message": "this will not get captured by express" + }, + "culprit": " (server/coffee.js)", + "grouping_key": "b9e1027f29c221763f864f6fa2ad9f5e" + } + }, + "sort": [1524675854533] + } + ] + } + } + } + ] + } + } +} diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/createErrorGroupWatch.js b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/createErrorGroupWatch.js index 019fa767030c1c..e1b9de2f40f37c 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/createErrorGroupWatch.js +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/Watcher/createErrorGroupWatch.js @@ -38,7 +38,7 @@ export async function createErrorGroupWatch({ const apmIndexPattern = chrome.getInjected('apmIndexPattern'); const slackUrlPath = getSlackPathUrl(slackUrl); - const emailTemplate = `Your service "{{ctx.metadata.serviceName}}" has error groups which exceeds {{ctx.metadata.threshold}} occurrences within "{{ctx.metadata.timeRangeHumanReadable}}" + const emailTemplate = `Your service "{{ctx.metadata.serviceName}}" has error groups which exceeds {{ctx.metadata.threshold}} occurrences within "{{ctx.metadata.timeRangeValue}}{{ctx.metadata.timeRangeUnit}}" {{#ctx.payload.aggregations.error_groups.buckets}} {{sample.hits.hits.0._source.error.log.message}}{{^sample.hits.hits.0._source.error.log.message}}{{sample.hits.hits.0._source.error.exception.message}}{{/sample.hits.hits.0._source.error.log.message}} @@ -46,7 +46,7 @@ export async function createErrorGroupWatch({ {{doc_count}} occurrences {{/ctx.payload.aggregations.error_groups.buckets}}`.replace(/\n/g, '
'); - const slackTemplate = `Your service "{{ctx.metadata.serviceName}}" has error groups which exceeds {{ctx.metadata.threshold}} occurrences within "{{ctx.metadata.timeRangeHumanReadable}}" + const slackTemplate = `Your service "{{ctx.metadata.serviceName}}" has error groups which exceeds {{ctx.metadata.threshold}} occurrences within "{{ctx.metadata.timeRangeValue}}{{ctx.metadata.timeRangeUnit}}" {{#ctx.payload.aggregations.error_groups.buckets}} >*{{sample.hits.hits.0._source.error.log.message}}{{^sample.hits.hits.0._source.error.log.message}}{{sample.hits.hits.0._source.error.exception.message}}{{/sample.hits.hits.0._source.error.log.message}}* >{{#sample.hits.hits.0._source.error.culprit}}\`{{sample.hits.hits.0._source.error.culprit}}\`{{/sample.hits.hits.0._source.error.culprit}}{{^sample.hits.hits.0._source.error.culprit}}N/A{{/sample.hits.hits.0._source.error.culprit}} @@ -59,8 +59,8 @@ export async function createErrorGroupWatch({ trigger: 'This value must be changed in trigger section', serviceName, threshold, - timeRange, - timeRangeHumanReadable: timeRange.replace('now-', ''), + timeRangeValue: timeRange.value, + timeRangeUnit: timeRange.unit, slackUrlPath }, trigger: { @@ -80,7 +80,8 @@ export async function createErrorGroupWatch({ { range: { '@timestamp': { - gte: '{{ctx.metadata.timeRange}}' + gte: + 'now-{{ctx.metadata.timeRangeValue}}{{ctx.metadata.timeRangeUnit}}' } } } @@ -159,7 +160,7 @@ export async function createErrorGroupWatch({ if (!isEmpty(emails)) { body.actions.email = { email: { - to: '{{ctx.metadata.emails}}', + to: '{{#join}}ctx.metadata.emails{{/join}}', subject: `"{{ctx.metadata.serviceName}}" has error groups which exceeds the threshold`, body: { html: emailTemplate diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/index.js b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/index.js index 409cfc0d64e6f0..494fe9fb14adca 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/index.js +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/index.js @@ -7,22 +7,16 @@ import { connect } from 'react-redux'; import ErrorGroupOverview from './view'; import { getUrlParams } from '../../../store/urlParams'; -import { - getErrorGroupList, - loadErrorGroupList -} from '../../../store/errorGroupList'; +import { getLicense } from '../../../store/reactReduxRequest/license'; function mapStateToProps(state = {}) { return { urlParams: getUrlParams(state), - errorGroupList: getErrorGroupList(state), location: state.location, - license: state.license + license: getLicense(state) }; } -const mapDispatchToProps = { - loadErrorGroupList -}; +const mapDispatchToProps = {}; export default connect(mapStateToProps, mapDispatchToProps)(ErrorGroupOverview); diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/view.js b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/view.js index 83c52ddc0e1cb5..c6fd3ee9502bb4 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/view.js +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/view.js @@ -6,30 +6,12 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import withErrorHandler from '../../shared/withErrorHandler'; import { HeaderContainer } from '../../shared/UIComponents'; import TabNavigation from '../../shared/TabNavigation'; import List from './List'; -import { getKey } from '../../../store/apiHelpers'; import WatcherFlyout from './Watcher/WatcherFlyOut'; import OpenWatcherDialogButton from './Watcher/OpenWatcherDialogButton'; - -function maybeLoadList(props) { - const { serviceName, start, end, q, sortBy, sortOrder } = props.urlParams; - const keyArgs = { - serviceName, - start, - end, - q, - sortBy, - sortOrder - }; - const key = getKey(keyArgs, false); - - if (serviceName && start && end && props.errorGroupList.key !== key) { - props.loadErrorGroupList(keyArgs); - } -} +import { ErrorGroupDetailsRequest } from '../../../store/reactReduxRequest/errorGroupList'; class ErrorGroupOverview extends Component { state = { @@ -44,17 +26,9 @@ class ErrorGroupOverview extends Component { this.setState({ isFlyoutOpen: false }); }; - componentDidMount() { - maybeLoadList(this.props); - } - - componentWillReceiveProps(nextProps) { - maybeLoadList(nextProps); - } - render() { - const { license, location } = this.props; - const { serviceName } = this.props.urlParams; + const { license, location, urlParams } = this.props; + const { serviceName } = urlParams; return (
@@ -67,15 +41,16 @@ class ErrorGroupOverview extends Component { - ( + + )} />
@@ -87,4 +62,4 @@ ErrorGroupOverview.propTypes = { location: PropTypes.object.isRequired }; -export default withErrorHandler(ErrorGroupOverview, ['errorGroupList']); +export default ErrorGroupOverview; diff --git a/x-pack/plugins/apm/public/components/app/Main/GlobalProgess/index.js b/x-pack/plugins/apm/public/components/app/Main/GlobalProgess/index.js index d1465163e7adb8..c8173d88343e98 100644 --- a/x-pack/plugins/apm/public/components/app/Main/GlobalProgess/index.js +++ b/x-pack/plugins/apm/public/components/app/Main/GlobalProgess/index.js @@ -10,7 +10,10 @@ import { some, get } from 'lodash'; import { STATUS } from '../../../../constants/index'; function getIsLoading(state) { - return some(state, subState => get(subState, 'status') === STATUS.LOADING); + return some( + state.reactReduxRequest, + subState => get(subState, 'status') === STATUS.LOADING + ); } function mapStateToProps(state = {}) { diff --git a/x-pack/plugins/apm/public/components/app/Main/GlobalProgess/view.js b/x-pack/plugins/apm/public/components/app/Main/GlobalProgess/view.js index b9847e50cf4084..2d02b8bd579afc 100644 --- a/x-pack/plugins/apm/public/components/app/Main/GlobalProgess/view.js +++ b/x-pack/plugins/apm/public/components/app/Main/GlobalProgess/view.js @@ -5,12 +5,14 @@ */ import React from 'react'; -import { EuiProgress } from '@elastic/eui'; +import { EuiProgress, EuiDelayHide } from '@elastic/eui'; export default ({ isLoading }) => { - if (!isLoading) { - return null; - } - - return ; + return ( + } + /> + ); }; diff --git a/x-pack/plugins/apm/public/components/app/Main/LicenseChecker/index.js b/x-pack/plugins/apm/public/components/app/Main/LicenseChecker/index.js index 55d9601eef6e7c..00fed7c3ed20c9 100644 --- a/x-pack/plugins/apm/public/components/app/Main/LicenseChecker/index.js +++ b/x-pack/plugins/apm/public/components/app/Main/LicenseChecker/index.js @@ -3,18 +3,21 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; +import { STATUS } from '../../../../constants/index'; +import { LicenceRequest } from '../../../../store/reactReduxRequest/license'; -import { connect } from 'react-redux'; -import LicenseChecker from './view'; -import { loadLicense } from '../../../../store/license'; - -function mapStateToProps(state = {}) { - return { - license: state.license - }; +function LicenseChecker() { + return ( + { + if (status === STATUS.SUCCESS && !data.license.isActive) { + window.location = '#/invalid-license'; + } + return null; + }} + /> + ); } -const mapDispatchToProps = { - loadLicense -}; -export default connect(mapStateToProps, mapDispatchToProps)(LicenseChecker); +export default LicenseChecker; diff --git a/x-pack/plugins/apm/public/components/app/Main/LicenseChecker/view.js b/x-pack/plugins/apm/public/components/app/Main/LicenseChecker/view.js deleted file mode 100644 index 0ba124dbf12f59..00000000000000 --- a/x-pack/plugins/apm/public/components/app/Main/LicenseChecker/view.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Component } from 'react'; -import { STATUS } from '../../../../constants/index'; - -function maybeLoadLicense(props) { - if (!props.license.status) { - props.loadLicense(); - } -} - -class LicenseChecker extends Component { - componentDidMount() { - maybeLoadLicense(this.props); - } - - componentWillReceiveProps(nextProps) { - if ( - nextProps.license.status === STATUS.SUCCESS && - !nextProps.license.data.license.isActive - ) { - window.location = '#/invalid-license'; - } - - maybeLoadLicense(nextProps); - } - - render() { - return null; - } -} - -export default LicenseChecker; diff --git a/x-pack/plugins/apm/public/components/app/Main/index.js b/x-pack/plugins/apm/public/components/app/Main/index.js index f0679975ae0e3c..ef717a12309651 100644 --- a/x-pack/plugins/apm/public/components/app/Main/index.js +++ b/x-pack/plugins/apm/public/components/app/Main/index.js @@ -8,8 +8,6 @@ import React from 'react'; import styled from 'styled-components'; import { Route, Switch } from 'react-router-dom'; import { routes } from './routeConfig'; -import GlobalProgess from './GlobalProgess'; -import LicenseChecker from './LicenseChecker'; import ScrollToTopOnPathChange from './ScrollToTopOnPathChange'; import { px, units, unit } from '../../../style/variables'; import ConnectRouterToRedux from '../../shared/ConnectRouterToRedux'; @@ -22,8 +20,6 @@ const MainContainer = styled.div` export default function Main() { return ( - - {routes.map((route, i) => { diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/List/ListItem.js b/x-pack/plugins/apm/public/components/app/ServiceOverview/List/ListItem.js index 08703c6deb8c09..efff18080ee414 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/List/ListItem.js +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/List/ListItem.js @@ -52,7 +52,7 @@ function ListItem({ service }) { - + {formatString(serviceName)} diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/List/__test__/__snapshots__/List.test.js.snap b/x-pack/plugins/apm/public/components/app/ServiceOverview/List/__test__/__snapshots__/List.test.js.snap index 4e45e3be686a9b..17b8fb33a78e02 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/List/__test__/__snapshots__/List.test.js.snap +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/List/__test__/__snapshots__/List.test.js.snap @@ -111,7 +111,7 @@ exports[`ErrorGroupOverview -> List should render empty state 1`] = ` Oops! You should try another time range. If that's no good, there's always the
diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/List/index.js b/x-pack/plugins/apm/public/components/app/ServiceOverview/List/index.js index 00e50ff55d2ec0..700793b2d95706 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/List/index.js +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/List/index.js @@ -5,7 +5,7 @@ */ import React, { Component } from 'react'; - +import PropTypes from 'prop-types'; import FilterableAPMTable from '../../../shared/APMTable/FilterableAPMTable'; import { AlignmentKuiTableHeaderCell } from '../../../shared/APMTable/APMTable'; @@ -79,4 +79,12 @@ class List extends Component { } } +List.propTypes = { + items: PropTypes.array +}; + +List.defaultProps = { + items: [] +}; + export default List; diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/index.js b/x-pack/plugins/apm/public/components/app/ServiceOverview/index.js index 3cc6f7c12b46ff..b751c83b83392e 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/index.js +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/index.js @@ -6,7 +6,7 @@ import { connect } from 'react-redux'; import ServiceOverview from './view'; -import { loadServiceList, getServiceList } from '../../../store/serviceList'; +import { getServiceList } from '../../../store/reactReduxRequest/serviceList'; import { getUrlParams } from '../../../store/urlParams'; import sorting, { changeServiceSorting } from '../../../store/sorting'; @@ -19,7 +19,6 @@ function mapStateToProps(state = {}) { } const mapDispatchToProps = { - loadServiceList, changeServiceSorting }; export default connect(mapStateToProps, mapDispatchToProps)(ServiceOverview); diff --git a/x-pack/plugins/apm/public/components/app/ServiceOverview/view.js b/x-pack/plugins/apm/public/components/app/ServiceOverview/view.js index c5a156c726bf57..f9cd9e71ec3b91 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceOverview/view.js +++ b/x-pack/plugins/apm/public/components/app/ServiceOverview/view.js @@ -5,52 +5,40 @@ */ import React, { Component } from 'react'; -import withErrorHandler from '../../shared/withErrorHandler'; import { STATUS } from '../../../constants'; import { isEmpty } from 'lodash'; import { loadAgentStatus } from '../../../services/rest'; import { KibanaLink } from '../../../utils/url'; import { EuiButton } from '@elastic/eui'; import List from './List'; -import { getKey } from '../../../store/apiHelpers'; import { HeaderContainer } from '../../shared/UIComponents'; -function fetchData(props) { - const { start, end } = props.urlParams; - const key = getKey({ start, end }); - - if (key && props.serviceList.key !== key) { - props.loadServiceList({ start, end }); - } -} +import { ServiceListRequest } from '../../../store/reactReduxRequest/serviceList'; class ServiceOverview extends Component { state = { noHistoricalDataFound: false }; - checkForHistoricalData({ serviceList }) { + async checkForHistoricalData({ serviceList }) { if (serviceList.status === STATUS.SUCCESS && isEmpty(serviceList.data)) { - loadAgentStatus().then(result => { - if (!result.dataFound) { - this.setState({ noHistoricalDataFound: true }); - } - }); + const result = await loadAgentStatus(); + if (!result.dataFound) { + this.setState({ noHistoricalDataFound: true }); + } } } componentDidMount() { - fetchData(this.props); this.checkForHistoricalData(this.props); } componentWillReceiveProps(nextProps) { - fetchData(nextProps); this.checkForHistoricalData(nextProps); } render() { - const { serviceList, changeServiceSorting, serviceSorting } = this.props; + const { changeServiceSorting, serviceSorting, urlParams } = this.props; const { noHistoricalDataFound } = this.state; const emptyMessageHeading = noHistoricalDataFound @@ -68,12 +56,17 @@ class ServiceOverview extends Component { - ( + + )} />
); @@ -90,4 +83,4 @@ function SetupInstructionsLink({ buttonFill = false }) { ); } -export default withErrorHandler(ServiceOverview, ['serviceList']); +export default ServiceOverview; diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Charts/index.js b/x-pack/plugins/apm/public/components/app/TransactionDetails/Charts/index.js deleted file mode 100644 index 4549f47a49fbf5..00000000000000 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Charts/index.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { connect } from 'react-redux'; -import Charts from '../../../shared/charts/TransactionCharts'; -import { getUrlParams } from '../../../../store/urlParams'; -import { - getDetailsCharts, - loadDetailsCharts -} from '../../../../store/detailsCharts'; -import { getKey } from '../../../../store/apiHelpers'; - -function mapStateToProps(state = {}) { - return { - urlParams: getUrlParams(state), - charts: getDetailsCharts(state) - }; -} - -const mapDispatchToProps = dispatch => ({ - loadCharts: props => { - const { - serviceName, - start, - end, - transactionType, - transactionName - } = props.urlParams; - const key = getKey({ - serviceName, - start, - end, - transactionType, - transactionName - }); - - if (key && props.charts.key !== key) { - dispatch( - loadDetailsCharts({ - serviceName, - start, - end, - transactionType, - transactionName - }) - ); - } - } -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Charts); diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.js b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.js index 96e83d8eec6e03..57e4086d3211bc 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.js +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/index.js @@ -7,21 +7,13 @@ import { connect } from 'react-redux'; import Distribution from './view'; import { getUrlParams } from '../../../../store/urlParams'; -import { - loadTransactionDistribution, - getTransactionDistribution -} from '../../../../store/transactionDistribution'; function mapStateToProps(state = {}) { return { urlParams: getUrlParams(state), - distribution: getTransactionDistribution(state), location: state.location }; } -const mapDispatchToProps = { - loadTransactionDistribution -}; - +const mapDispatchToProps = {}; export default connect(mapStateToProps, mapDispatchToProps)(Distribution); diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/view.js b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/view.js index eef8ee88503708..9e07253bd1cde0 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/view.js +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Distribution/view.js @@ -13,7 +13,6 @@ import { HeaderSmall } from '../../../shared/UIComponents'; import EmptyMessage from '../../../shared/EmptyMessage'; import { getTimeFormatter, timeUnit } from '../../../../utils/formatters'; import SamplingTooltip from './SamplingTooltip'; -import { getKey } from '../../../../store/apiHelpers'; export function getFormattedBuckets(buckets, bucketSize) { if (!buckets) { @@ -32,29 +31,7 @@ export function getFormattedBuckets(buckets, bucketSize) { }); } -function loadTransactionDistribution(props) { - const { serviceName, start, end, transactionName } = props.urlParams; - const key = getKey({ serviceName, start, end, transactionName }); - - if (key && props.distribution.key !== key) { - props.loadTransactionDistribution({ - serviceName, - start, - end, - transactionName - }); - } -} - class Distribution extends Component { - componentDidMount() { - loadTransactionDistribution(this.props); - } - - componentWillReceiveProps(nextProps) { - loadTransactionDistribution(nextProps); - } - formatYShort = t => { return `${t} ${unitShort(this.props.urlParams.transactionType)}`; }; @@ -67,11 +44,11 @@ class Distribution extends Component { const { location, distribution } = this.props; const buckets = getFormattedBuckets( - distribution.data.buckets, - distribution.data.bucketSize + distribution.buckets, + distribution.bucketSize ); - const isEmpty = distribution.data.totalHits === 0; + const isEmpty = distribution.totalHits === 0; const xMax = d3.max(buckets, d => d.x); const timeFormatter = getTimeFormatter(xMax); const unit = timeUnit(xMax); @@ -99,7 +76,7 @@ class Distribution extends Component { { if (bucket.sampled && bucket.y > 0) { @@ -143,7 +120,9 @@ function unitLong(type, count) { } Distribution.propTypes = { - location: PropTypes.object.isRequired + urlParams: PropTypes.object.isRequired, + location: PropTypes.object.isRequired, + distribution: PropTypes.object }; export default Distribution; diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/Spans/index.js b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/Spans/index.js index cc3fbe68aec605..08d71a00313170 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/Spans/index.js +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/Spans/index.js @@ -7,17 +7,13 @@ import { connect } from 'react-redux'; import Spans from './view'; import { getUrlParams } from '../../../../../store/urlParams'; -import { loadSpans, getSpans } from '../../../../../store/spans'; function mapStateToProps(state = {}) { return { urlParams: getUrlParams(state), - spans: getSpans(state), location: state.location }; } -const mapDispatchToProps = { - loadSpans -}; +const mapDispatchToProps = {}; export default connect(mapStateToProps, mapDispatchToProps)(Spans); diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/Spans/view.js b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/Spans/view.js index ac94e71e9712e0..b4f10bc50cccec 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/Spans/view.js +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/Spans/view.js @@ -17,7 +17,7 @@ import Timeline from '../../../../shared/charts/Timeline'; import EmptyMessage from '../../../../shared/EmptyMessage'; import { getFeatureDocs } from '../../../../../utils/documentation'; import { ExternalLink } from '../../../../../utils/url'; -import { getKey } from '../../../../../store/apiHelpers'; +import { SpansRequest } from '../../../../../store/reactReduxRequest/spans'; const Container = styled.div` transition: 0.1s padding ease; @@ -42,94 +42,85 @@ const TIMELINE_MARGINS = { }; class Spans extends PureComponent { - componentDidMount() { - loadSpans(this.props); - } - - componentWillReceiveProps(nextProps) { - loadSpans(nextProps); - } - render() { - const { spans, agentName, urlParams, location } = this.props; - if (isEmpty(spans.data.spans)) { - return ( - - ); - } - - const spanTypes = uniq( - spans.data.spanTypes.map(({ type }) => getPrimaryType(type)) - ); - - const getSpanColor = getColorByType(spanTypes); - - const totalDuration = spans.data.duration; - const spanContainerHeight = 58; - const timelineHeight = spanContainerHeight * spans.data.spans.length; - + const { agentName, urlParams, location, droppedSpans } = this.props; return ( -
- - - ({ - label: getSpanLabel(type), - color: getSpanColor(type) - }))} - transactionName={urlParams.transactionName} - /> - } - duration={totalDuration} - height={timelineHeight} - margins={TIMELINE_MARGINS} - /> -
- {spans.data.spans.map(span => ( - - ))} + { + if (isEmpty(spans.data.spans)) { + return ( + + ); + } + + const spanTypes = uniq( + spans.data.spanTypes.map(({ type }) => getPrimaryType(type)) + ); + + const getSpanColor = getColorByType(spanTypes); + + const totalDuration = spans.data.duration; + const spanContainerHeight = 58; + const timelineHeight = spanContainerHeight * spans.data.spans.length; + + return ( +
+ + + ({ + label: getSpanLabel(type), + color: getSpanColor(type) + }))} + transactionName={urlParams.transactionName} + /> + } + duration={totalDuration} + height={timelineHeight} + margins={TIMELINE_MARGINS} + /> +
+ {spans.data.spans.map(span => ( + + ))} +
+
+
+ + {droppedSpans > 0 && ( + + {droppedSpans} spans dropped due to limit of{' '} + {spans.data.spans.length}.{' '} + + + )}
- - - - {this.props.droppedSpans > 0 && ( - - {this.props.droppedSpans} spans dropped due to limit of{' '} - {spans.data.spans.length}.{' '} - - - )} -
+ ); + }} + /> ); } } -function loadSpans(props) { - const { serviceName, start, end, transactionId } = props.urlParams; - const key = getKey({ serviceName, start, end, transactionId }); - if (key && props.spans.key !== key) { - props.loadSpans({ serviceName, start, end, transactionId }); - } -} - function DroppedSpansDocsLink({ agentName }) { const docs = getFeatureDocs('dropped-spans', agentName); @@ -185,7 +176,10 @@ function getPrimaryType(type) { } Spans.propTypes = { - location: PropTypes.object.isRequired + location: PropTypes.object.isRequired, + agentName: PropTypes.string.isRequired, + urlParams: PropTypes.object.isRequired, + droppedSpans: PropTypes.number.isRequired }; export default Spans; diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/index.js b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/index.js index 5bde95b4a88b81..ca4a4cc626c798 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/index.js +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/index.js @@ -6,18 +6,12 @@ import { connect } from 'react-redux'; import Transaction from './view'; -import { getUrlParams } from '../../../../store/urlParams'; -import { loadTransaction, getTransaction } from '../../../../store/transaction'; function mapStateToProps(state = {}) { return { - urlParams: getUrlParams(state), - transaction: getTransaction(state), location: state.location }; } -const mapDispatchToProps = { - loadTransaction -}; +const mapDispatchToProps = {}; export default connect(mapStateToProps, mapDispatchToProps)(Transaction); diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/view.js b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/view.js index 27eadd5acb2041..f9e64ad300df9c 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/view.js +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/Transaction/view.js @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Component } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import styled from 'styled-components'; import { unit, @@ -31,16 +32,6 @@ import { import { fromQuery, toQuery, history } from '../../../../utils/url'; import { asTime } from '../../../../utils/formatters'; import EmptyMessage from '../../../shared/EmptyMessage'; -import { getKey } from '../../../../store/apiHelpers'; - -function loadTransaction(props) { - const { serviceName, start, end, transactionId } = props.urlParams; - const key = getKey({ serviceName, start, end, transactionId }); - - if (key && props.transaction.key !== key) { - props.loadTransaction({ serviceName, start, end, transactionId }); - } -} const Container = styled.div` position: relative; @@ -81,131 +72,129 @@ function getTabs(transactionData) { return getLevelOneProps(dynamicProps); } -class Transaction extends Component { - componentDidMount() { - loadTransaction(this.props); - } +function Transaction({ transaction, location, urlParams }) { + const { transactionId } = urlParams; - componentWillReceiveProps(nextProps) { - loadTransaction(nextProps); + if (isEmpty(transaction)) { + return ( + + ); } - render() { - const { transaction, location } = this.props; - const { transactionId } = this.props.urlParams; - - if (isEmpty(transaction.data)) { - return ( - - ); + const timestamp = get(transaction, '@timestamp'); + const url = get(transaction, 'context.request.url.full', 'N/A'); + const duration = get(transaction, 'transaction.duration.us'); + const stickyProperties = [ + { + label: 'Duration', + fieldName: 'transaction.duration.us', + val: duration ? asTime(duration) : 'N/A' + }, + { + label: 'Result', + fieldName: 'transaction.result', + val: get(transaction, 'transaction.result', 'N/A') + }, + { + label: 'User ID', + fieldName: 'context.user.id', + val: get(transaction, 'context.user.id', 'N/A') } - - const timestamp = get(transaction, 'data.@timestamp'); - const url = get(transaction.data, 'context.request.url.full', 'N/A'); - const duration = get(transaction.data, 'transaction.duration.us'); - const stickyProperties = [ - { - label: 'Duration', - fieldName: 'transaction.duration.us', - val: duration ? asTime(duration) : 'N/A' + ]; + + const agentName = get(transaction, SERVICE_AGENT_NAME); + const tabs = getTabs(transaction); + const currentTab = getCurrentTab(tabs, urlParams.detailTab); + + const discoverQuery = { + _a: { + interval: 'auto', + query: { + language: 'lucene', + query: `${PROCESSOR_EVENT}:transaction AND ${TRANSACTION_ID}:${transactionId}` }, - { - label: 'Result', - fieldName: 'transaction.result', - val: get(transaction.data, 'transaction.result', 'N/A') - }, - { - label: 'User ID', - fieldName: 'context.user.id', - val: get(transaction.data, 'context.user.id', 'N/A') - } - ]; - - const agentName = get(transaction.data, SERVICE_AGENT_NAME); - const tabs = getTabs(transaction.data); - const currentTab = getCurrentTab(tabs, this.props.urlParams.detailTab); - - const discoverQuery = { - _a: { - interval: 'auto', - query: { - language: 'lucene', - query: `${PROCESSOR_EVENT}:transaction AND ${TRANSACTION_ID}:${transactionId}` - }, - sort: { '@timestamp': 'desc' } - } - }; - - return ( - - - - Transaction sample - - - {`View transaction in Discover`} - - - - - - - {[DEFAULT_TAB, ...tabs].map(key => { - return ( - { - history.replace({ - ...location, - search: fromQuery({ - ...toQuery(location.search), - detailTab: key - }) - }); - }} - selected={currentTab === key} - key={key} - > - {capitalize(key)} - - ); - })} - - - - {currentTab === DEFAULT_TAB ? ( - + + + Transaction sample + + + {`View transaction in Discover`} + + + + + + + {[DEFAULT_TAB, ...tabs].map(key => { + return ( + { + history.replace({ + ...location, + search: fromQuery({ + ...toQuery(location.search), + detailTab: key + }) + }); + }} + selected={currentTab === key} + key={key} + > + {capitalize(key)} + + ); + })} + + + + {currentTab === DEFAULT_TAB ? ( + + ) : ( + + - ) : ( - - - - )} - - - ); - } + + )} + +
+ ); } +Transaction.propTypes = { + urlParams: PropTypes.object.isRequired, + transaction: PropTypes.object +}; + +Transaction.defaultProps = { + transaction: {} +}; + export default Transaction; diff --git a/x-pack/plugins/apm/public/components/app/TransactionDetails/view.js b/x-pack/plugins/apm/public/components/app/TransactionDetails/view.js index 60a0dec6c0ae46..53f280d2cc5f53 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionDetails/view.js +++ b/x-pack/plugins/apm/public/components/app/TransactionDetails/view.js @@ -8,15 +8,34 @@ import React from 'react'; import { HeaderLarge } from '../../shared/UIComponents'; import Transaction from './Transaction'; import Distribution from './Distribution'; -import Charts from './Charts'; +import { DetailsChartsRequest } from '../../../store/reactReduxRequest/detailsCharts'; +import Charts from '../../shared/charts/TransactionCharts'; +import { TransactionDistributionRequest } from '../../../store/reactReduxRequest/transactionDistribution'; +import { TransactionDetailsRequest } from '../../../store/reactReduxRequest/transactionDetails'; function TransactionDetails({ urlParams }) { return (
{urlParams.transactionName} - - - + + } + /> + + ( + + )} + /> + + ( + + )} + />
); } diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/Charts/index.js b/x-pack/plugins/apm/public/components/app/TransactionOverview/Charts/index.js deleted file mode 100644 index 3b3c960ed819dd..00000000000000 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/Charts/index.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { connect } from 'react-redux'; -import Charts from '../../../shared/charts/TransactionCharts'; -import { getUrlParams } from '../../../../store/urlParams'; -import { - getOverviewCharts, - loadOverviewCharts -} from '../../../../store/overviewCharts'; -import { getKey } from '../../../../store/apiHelpers'; - -function mapStateToProps(state = {}) { - return { - urlParams: getUrlParams(state), - charts: getOverviewCharts(state) - }; -} - -const mapDispatchToProps = dispatch => ({ - loadCharts: props => { - const { serviceName, start, end, transactionType } = props.urlParams; - const key = getKey({ serviceName, start, end, transactionType }); - - if (key && props.charts.key !== key) { - dispatch( - loadOverviewCharts({ serviceName, start, end, transactionType }) - ); - } - } -}); - -export default connect(mapStateToProps, mapDispatchToProps)(Charts); diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/List/ListItem.js b/x-pack/plugins/apm/public/components/app/TransactionOverview/List/ListItem.js index 9abcd7214b2a2a..d51447f7ee8d42 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/List/ListItem.js +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/List/ListItem.js @@ -86,7 +86,7 @@ function TransactionListItem({ serviceName, transaction, type, impact }) { - + {transactionName || 'N/A'} diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/List/index.js b/x-pack/plugins/apm/public/components/app/TransactionOverview/List/index.js index 7f1f86f2cae1b5..c436d175a83cb8 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/List/index.js +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/List/index.js @@ -5,7 +5,7 @@ */ import React, { Component } from 'react'; - +import PropTypes from 'prop-types'; import { get } from 'lodash'; import { TRANSACTION_ID } from '../../../../../common/constants'; @@ -15,7 +15,6 @@ import { AlignmentKuiTableHeaderCell } from '../../../shared/APMTable/APMTable'; import FilterableAPMTable from '../../../shared/APMTable/FilterableAPMTable'; import ListItem from './ListItem'; import ImpactTooltip from './ImpactTooltip'; -import withService from '../../../shared/withService'; const getRelativeImpact = (impact, impactMin, impactMax) => Math.max((impact - impactMin) / Math.max(impactMax - impactMin, 1) * 100, 1); @@ -31,12 +30,12 @@ function avgLabel(agentName) { class List extends Component { render() { const { - serviceName, - service, - type, - items, + agentName, changeTransactionSorting, - transactionSorting + items, + serviceName, + transactionSorting, + type } = this.props; const renderHead = () => { @@ -46,7 +45,7 @@ class List extends Component { key: 'avg', sortable: true, alignRight: true, - label: avgLabel(service.data.agentName) + label: avgLabel(agentName) }, { key: 'p95', @@ -129,4 +128,12 @@ class List extends Component { } } -export default withService(List); +List.propTypes = { + agentName: PropTypes.string, + changeTransactionSorting: PropTypes.func.isRequired, + items: PropTypes.array, + transactionSorting: PropTypes.object.isRequired, + type: PropTypes.string +}; + +export default List; diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.js b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.js index 85659586fc60ef..7873c9b53a661c 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.js +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/TransactionOverview.test.js @@ -6,20 +6,13 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { TransactionOverview } from '../view'; -import { getKey } from '../../../../store/apiHelpers'; +import TransactionOverview from '../view'; +import { toJson } from '../../../../utils/testHelpers'; jest.mock('../../../../utils/timepicker', () => {}); const setup = () => { const props = { - service: { - data: {} - }, - transactionList: { - data: [] - }, - urlParams: {}, - loadTransactionList: jest.fn() + urlParams: { transactionType: 'request', serviceName: 'MyServiceName' } }; const wrapper = shallow(); @@ -28,55 +21,7 @@ const setup = () => { describe('TransactionOverview', () => { it('should not call loadTransactionList without any props', () => { - const { props } = setup(); - expect(props.loadTransactionList).not.toHaveBeenCalled(); - }); - - it('should call loadTransactionList when props are given, and list is not loading', () => { - const { props, wrapper } = setup(); - - wrapper.setProps({ - urlParams: { - serviceName: 'myServiceName', - start: 'myStart', - end: 'myEnd', - transactionType: 'myTransactionType' - }, - transactionList: { - data: [], - status: undefined - } - }); - - expect(props.loadTransactionList).toHaveBeenCalledWith({ - serviceName: 'myServiceName', - end: 'myEnd', - start: 'myStart', - transactionType: 'myTransactionType' - }); - }); - - it('should not call loadTransactionList, if list is already loading', () => { - const { props, wrapper } = setup(); - wrapper.setProps({ - urlParams: { - serviceName: 'myServiceName', - start: 'myStart', - end: 'myEnd', - transactionType: 'myTransactionType' - }, - transactionList: { - key: getKey({ - serviceName: 'myServiceName', - start: 'myStart', - end: 'myEnd', - transactionType: 'myTransactionType' - }), - data: [], - status: 'LOADING' - } - }); - - expect(props.loadTransactionList).not.toHaveBeenCalled(); + const { wrapper } = setup(); + expect(toJson(wrapper)).toMatchSnapshot(); }); }); diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.js.snap b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.js.snap new file mode 100644 index 00000000000000..2ed40fb92405f1 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/__jest__/__snapshots__/TransactionOverview.test.js.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TransactionOverview should not call loadTransactionList without any props 1`] = ` +
+ + MyServiceName + + + + + Request + + +
+`; diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.js b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.js index 8499e002d523e0..fe69e2faca1a9c 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.js +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.js @@ -8,21 +8,16 @@ import { connect } from 'react-redux'; import TransactionOverview from './view'; import { getUrlParams } from '../../../store/urlParams'; import sorting, { changeTransactionSorting } from '../../../store/sorting'; -import { - getTransactionList, - loadTransactionList -} from '../../../store/transactionList'; function mapStateToProps(state = {}) { return { urlParams: getUrlParams(state), - transactionList: getTransactionList(state), + transactionSorting: sorting(state, 'transaction').sorting.transaction }; } const mapDispatchToProps = { - loadTransactionList, changeTransactionSorting }; diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/view.js b/x-pack/plugins/apm/public/components/app/TransactionOverview/view.js index 7e8bd6dad961fa..ef68a7da728202 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/view.js +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/view.js @@ -4,58 +4,80 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Component } from 'react'; -import withErrorHandler from '../../shared/withErrorHandler'; +import React from 'react'; +import PropTypes from 'prop-types'; import { HeaderLarge, HeaderMedium } from '../../shared/UIComponents'; import TabNavigation from '../../shared/TabNavigation'; -import Charts from './Charts'; +import Charts from '../../shared/charts/TransactionCharts'; import List from './List'; -import { getKey } from '../../../store/apiHelpers'; +import { OverviewChartsRequest } from '../../../store/reactReduxRequest/overviewCharts'; +import { TransactionListRequest } from '../../../store/reactReduxRequest/transactionList'; +import { ServiceDetailsRequest } from '../../../store/reactReduxRequest/serviceDetails'; -function loadTransactionList(props) { - const { serviceName, start, end, transactionType } = props.urlParams; - const key = getKey({ serviceName, start, end, transactionType }); - - if (key && props.transactionList.key !== key) { - props.loadTransactionList({ serviceName, start, end, transactionType }); - } +function ServiceDetailsAndTransactionList({ urlParams, render }) { + return ( + { + return ( + { + return render({ + transactionList: transactionList.data, + serviceDetails: serviceDetails.data + }); + }} + /> + ); + }} + /> + ); } -export class TransactionOverview extends Component { - componentDidMount() { - loadTransactionList(this.props); - } +export default function TransactionOverview({ + changeTransactionSorting, + transactionSorting, + urlParams +}) { + const { serviceName, transactionType } = urlParams; - componentWillReceiveProps(nextProps) { - loadTransactionList(nextProps); - } + return ( +
+ {serviceName} - render() { - const { serviceName, transactionType } = this.props.urlParams; - const { - changeTransactionSorting, - transactionSorting, - transactionList - } = this.props; + - return ( -
- {serviceName} - - - {transactionTypeLabel(transactionType)} - -
- ); - } + } + /> + + {transactionTypeLabel(transactionType)} + + { + return ( + + ); + }} + /> +
+ ); } +TransactionOverview.propTypes = { + urlParams: PropTypes.object.isRequired +}; + // TODO: This is duplicated in TabNavigation function transactionTypeLabel(type) { switch (type) { @@ -67,5 +89,3 @@ function transactionTypeLabel(type) { return type; } } - -export default withErrorHandler(TransactionOverview, ['transactionList']); diff --git a/x-pack/plugins/apm/public/components/shared/KueryBar/index.js b/x-pack/plugins/apm/public/components/shared/KueryBar/index.js new file mode 100644 index 00000000000000..e1a8baf74db7ba --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/KueryBar/index.js @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { connect } from 'react-redux'; +import view from './view'; +import { getUrlParams } from '../../../store/urlParams'; + +function mapStateToProps(state = {}) { + return { + location: state.location, + urlParams: getUrlParams(state) + }; +} + +export const KueryBar = connect(mapStateToProps)(view); diff --git a/x-pack/plugins/apm/public/components/shared/KueryBar/view.js b/x-pack/plugins/apm/public/components/shared/KueryBar/view.js new file mode 100644 index 00000000000000..fc9dd9be2bb50c --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/KueryBar/view.js @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { + history, + fromQuery, + toQuery, + legacyEncodeURIComponent +} from '../../../utils/url'; +import { debounce } from 'lodash'; + +import { EuiFieldSearch } from '@elastic/eui'; + +import { getAPMIndexPattern } from '../../../services/rest'; + +import { convertKueryToEsQuery, getSuggestions } from '../../../services/kuery'; +import styled from 'styled-components'; + +const Container = styled.div` + margin-bottom: 10px; +`; + +class KueryBarView extends Component { + state = { + indexPattern: null, + inputValue: this.props.urlParams.kuery || '' + }; + + componentDidMount() { + getAPMIndexPattern().then(indexPattern => { + this.setState({ indexPattern }); + }); + } + + componentWillReceiveProps(nextProps) { + const kuery = nextProps.urlParams.kuery; + if (kuery && !this.state.inputValue) { + this.setState({ inputValue: kuery }); + } + } + + updateUrl = debounce(kuery => { + const { location } = this.props; + const { indexPattern } = this.state; + + if (!indexPattern) { + return; + } + + getSuggestions(kuery, indexPattern).then( + suggestions => console.log(suggestions.map(suggestion => suggestion.text)) // eslint-disable-line no-console + ); + + try { + const res = convertKueryToEsQuery(kuery, indexPattern); + if (!res) { + return; + } + + history.replace({ + ...location, + search: fromQuery({ + ...toQuery(this.props.location.search), + kuery: legacyEncodeURIComponent(kuery) + }) + }); + } catch (e) { + console.log('Invalid kuery syntax'); // eslint-disable-line no-console + } + }, 200); + + onChange = event => { + const kuery = event.target.value; + this.setState({ inputValue: kuery }); + this.updateUrl(kuery); + }; + + render() { + return ( + + + + ); + } +} + +KueryBarView.propTypes = { + location: PropTypes.object.isRequired, + urlParams: PropTypes.object.isRequired +}; + +export default KueryBarView; diff --git a/x-pack/plugins/apm/public/components/shared/TabNavigation/view.js b/x-pack/plugins/apm/public/components/shared/TabNavigation/view.js index 4f5b094589b59e..284b66adde4ca1 100644 --- a/x-pack/plugins/apm/public/components/shared/TabNavigation/view.js +++ b/x-pack/plugins/apm/public/components/shared/TabNavigation/view.js @@ -8,7 +8,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import { TabLink } from '../UIComponents'; import styled from 'styled-components'; -import withService from '../withService'; import { unit, units, @@ -20,6 +19,7 @@ import { import { isEmpty } from 'lodash'; import TooltipOverlay from '../../shared/TooltipOverlay'; +import { ServiceDetailsRequest } from '../../../store/reactReduxRequest/serviceDetails'; const Container = styled.div` display: flex; @@ -59,39 +59,49 @@ function transactionTypeLabel(type) { } } -function TabNavigation({ urlParams, location, service }) { +function TabNavigation({ urlParams, location }) { const { serviceName, transactionType } = urlParams; const errorsSelected = location.pathname.includes('/errors'); - const { types } = service.data; return ( - {types.map(type => { - const label = transactionTypeLabel(type); - return ( - - Transaction type:
- {label} - - } - key={type} - > - - {label} - -
- ); - })} - {isEmpty(types) && ( - No transactions available. - )} + { + const { types } = serviceDetails.data; + + if (isEmpty(types)) { + return No transactions available.; + } + + return types.map(type => { + const label = transactionTypeLabel(type); + return ( + + Transaction type:
+ {label} + + } + key={type} + > + + {label} + +
+ ); + }); + }} + /> + - + Errors
@@ -102,4 +112,4 @@ TabNavigation.propTypes = { location: PropTypes.object.isRequired }; -export default withService(TabNavigation); +export default TabNavigation; diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.js b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.js index d56d41fca7541e..73d47110a4ecff 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.js +++ b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.js @@ -39,14 +39,6 @@ export class Charts extends Component { hoverIndex: null }; - componentDidMount() { - this.props.loadCharts(this.props); - } - - componentWillReceiveProps(nextProps) { - nextProps.loadCharts(nextProps); - } - onHover = hoverIndex => this.setState({ hoverIndex }); onMouseLeave = () => this.setState({ hoverIndex: null }); onSelectionEnd = selection => { @@ -56,11 +48,11 @@ export class Charts extends Component { }; getResponseTimeTickFormatter = t => { - return this.props.charts.data.noHits ? '- ms' : asMillis(t); + return this.props.charts.noHits ? '- ms' : asMillis(t); }; getResponseTimeTooltipFormatter = t => { - if (this.props.charts.data.noHits) { + if (this.props.charts.noHits) { return '- ms'; } else { return t == null ? 'N/A' : asMillis(t); @@ -70,12 +62,12 @@ export class Charts extends Component { getTPMFormatter = t => { const { urlParams, charts } = this.props; const unit = tpmUnit(urlParams.transactionType); - return charts.data.noHits ? `- ${unit}` : `${asInteger(t)} ${unit}`; + return charts.noHits ? `- ${unit}` : `${asInteger(t)} ${unit}`; }; render() { const { charts, urlParams } = this.props; - const { noHits, responseTimeSeries, tpmSeries } = charts.data; + const { noHits, responseTimeSeries, tpmSeries } = charts; return ( diff --git a/x-pack/plugins/apm/public/components/shared/withErrorHandler/index.js b/x-pack/plugins/apm/public/components/shared/withErrorHandler/index.js deleted file mode 100644 index 8c2c2d1effe0c0..00000000000000 --- a/x-pack/plugins/apm/public/components/shared/withErrorHandler/index.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { STATUS } from '../../../constants'; -import ErrorHandler from './view'; -import { getDisplayName } from '../HOCUtils'; -import { isEmpty } from 'lodash'; - -function withErrorHandler(WrappedComponent, dataNames) { - function HOC(props) { - const unavailableNames = dataNames.filter( - name => props[name].status === STATUS.FAILURE - ); - - if (!isEmpty(unavailableNames)) { - return ; - } - - return ; - } - - HOC.displayName = `WithErrorHandler(${getDisplayName(WrappedComponent)})`; - - return HOC; -} - -export default withErrorHandler; diff --git a/x-pack/plugins/apm/public/components/shared/withErrorHandler/view.js b/x-pack/plugins/apm/public/components/shared/withErrorHandler/view.js deleted file mode 100644 index 71d625ae02a9b4..00000000000000 --- a/x-pack/plugins/apm/public/components/shared/withErrorHandler/view.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import styled from 'styled-components'; -import { fontSizes } from '../../../style/variables'; - -function ErrorHandler({ names }) { - const ErrorWrap = styled.div` - font-size: ${fontSizes.large}; - `; - - return ( - -

Error

-

Failed to load data for: {names.join('\n')}

-

Please check the console or the server output.

-
- ); -} - -export default ErrorHandler; diff --git a/x-pack/plugins/apm/public/components/shared/withService/index.js b/x-pack/plugins/apm/public/components/shared/withService/index.js deleted file mode 100644 index 14fd1049839610..00000000000000 --- a/x-pack/plugins/apm/public/components/shared/withService/index.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { connect } from 'react-redux'; -import { getUrlParams } from '../../../store/urlParams'; -import { loadService, getService } from '../../../store/service'; -import getComponentWithService from './view'; -import { getDisplayName } from '../HOCUtils'; - -function withService(WrappedComponent) { - function mapStateToProps(state = {}, props) { - return { - service: getService(state), - urlParams: getUrlParams(state), - originalProps: props - }; - } - - const mapDispatchToProps = { - loadService - }; - - const HOC = getComponentWithService(WrappedComponent); - HOC.displayName = `WithService(${getDisplayName(WrappedComponent)})`; - - return connect(mapStateToProps, mapDispatchToProps)(HOC); -} - -export default withService; diff --git a/x-pack/plugins/apm/public/components/shared/withService/view.js b/x-pack/plugins/apm/public/components/shared/withService/view.js deleted file mode 100644 index 505f28622947f6..00000000000000 --- a/x-pack/plugins/apm/public/components/shared/withService/view.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component } from 'react'; -import { getKey } from '../../../store/apiHelpers'; - -function maybeLoadService(props) { - const { serviceName, start, end } = props.urlParams; - const key = getKey({ serviceName, start, end }); - - if (key && props.service.key !== key) { - props.loadService({ serviceName, start, end }); - } -} - -function getComponentWithService(WrappedComponent) { - return class extends Component { - componentDidMount() { - maybeLoadService(this.props); - } - - componentWillReceiveProps(nextProps) { - maybeLoadService(nextProps); - } - - render() { - return ( - - ); - } - }; -} - -export default getComponentWithService; diff --git a/x-pack/plugins/apm/public/index.js b/x-pack/plugins/apm/public/index.js index ccbb37ef828a3b..08fb47ae9ff356 100644 --- a/x-pack/plugins/apm/public/index.js +++ b/x-pack/plugins/apm/public/index.js @@ -6,7 +6,7 @@ import { uiModules } from 'ui/modules'; // eslint-disable-line no-unused-vars import chrome from 'ui/chrome'; -import React from 'react'; +import React, { Fragment } from 'react'; import { Provider } from 'react-redux'; import { Router } from 'react-router-dom'; import ReactDOM from 'react-dom'; @@ -21,6 +21,8 @@ import Breadcrumbs from './components/app/Main/Breadcrumbs'; import { initTimepicker } from './utils/timepicker'; import configureStore from './store/config/configureStore'; +import GlobalProgess from './components/app/Main/GlobalProgess'; +import LicenseChecker from './components/app/Main/LicenseChecker'; import { history } from './utils/url'; @@ -38,9 +40,13 @@ initTimepicker(history, store.dispatch, () => { ReactDOM.render( - -
- + + + + +
+ + , document.getElementById('react-apm-root') ); diff --git a/x-pack/plugins/apm/public/register_feature.js b/x-pack/plugins/apm/public/register_feature.js index 3822a477343357..5b75f189c2e254 100644 --- a/x-pack/plugins/apm/public/register_feature.js +++ b/x-pack/plugins/apm/public/register_feature.js @@ -18,7 +18,7 @@ if (chrome.getInjected('apmUiEnabled')) { description: 'Automatically collect in-depth performance metrics and ' + 'errors from inside your applications.', - icon: '/plugins/kibana/assets/app_apm.svg', + icon: 'apmApp', path: '/app/apm', showOnHomePage: true, category: FeatureCatalogueCategory.DATA diff --git a/x-pack/plugins/apm/public/services/kuery.js b/x-pack/plugins/apm/public/services/kuery.js new file mode 100644 index 00000000000000..453dc53adf5112 --- /dev/null +++ b/x-pack/plugins/apm/public/services/kuery.js @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + fromKueryExpression, + toElasticsearchQuery, + getSuggestionsProvider +} from 'ui/kuery'; + +export function convertKueryToEsQuery(kuery, indexPattern) { + const ast = fromKueryExpression(kuery); + return toElasticsearchQuery(ast, indexPattern); +} + +export async function getSuggestions(query, apmIndexPattern) { + const config = { + get: () => true + }; + + const getKuerySuggestions = getSuggestionsProvider({ + config, + indexPatterns: [apmIndexPattern] + }); + return getKuerySuggestions({ + query, + selectionStart: query.length, + selectionEnd: query.length + }); +} diff --git a/x-pack/plugins/apm/public/services/rest.js b/x-pack/plugins/apm/public/services/rest.js index 73c75d45154401..0af1390c0cf1a4 100644 --- a/x-pack/plugins/apm/public/services/rest.js +++ b/x-pack/plugins/apm/public/services/rest.js @@ -6,82 +6,95 @@ import 'isomorphic-fetch'; import { camelizeKeys } from 'humps'; -import url from 'url'; -import _ from 'lodash'; +import { kfetch } from 'ui/kfetch'; +import { memoize, isEmpty, first } from 'lodash'; import chrome from 'ui/chrome'; +import { convertKueryToEsQuery } from './kuery'; +import { getFromSavedObject } from 'ui/index_patterns/static_utils'; -async function callApi(options) { - const { pathname, query, camelcase, compact, ...urlOptions } = { - compact: true, // remove empty query args +async function callApi(fetchOptions, kibanaOptions) { + const combinedKibanaOptions = { camelcase: true, - credentials: 'same-origin', - method: 'GET', - headers: new Headers({ - 'Content-Type': 'application/json', - 'kbn-xsrf': true - }), - ...options + ...kibanaOptions }; - const fullUrl = url.format({ - pathname, - query: compact ? _.omit(query, val => val == null) : query - }); + const combinedFetchOptions = { + ...fetchOptions, + query: fetchOptions.query + }; - try { - const response = await fetch(fullUrl, urlOptions); - const json = await response.json(); - if (!response.ok) { - throw new Error(JSON.stringify(json, null, 4)); + const res = await kfetch(combinedFetchOptions, combinedKibanaOptions); + return combinedKibanaOptions.camelcase ? camelizeKeys(res) : res; +} + +export const getAPMIndexPattern = memoize(async () => { + const res = await callApi({ + pathname: chrome.addBasePath(`/api/saved_objects/_find`), + query: { + type: 'index-pattern' } - return camelcase ? camelizeKeys(json) : json; - } catch (err) { - console.error( - 'Rest request error with options:\n', - JSON.stringify(options, null, 4), - '\n', - err.message, - err.stack - ); - throw err; + }); + + if (isEmpty(res.savedObjects)) { + return {}; } -} + + const apmIndexPattern = chrome.getInjected('apmIndexPattern'); + const apmSavedObject = first( + res.savedObjects.filter( + savedObject => savedObject.attributes.title === apmIndexPattern + ) + ); + + return getFromSavedObject(apmSavedObject); +}); export async function loadLicense() { return callApi({ - pathname: chrome.addBasePath(`/api/xpack/v1/info`) + pathname: `/api/xpack/v1/info` }); } export async function loadServerStatus() { return callApi({ - pathname: chrome.addBasePath(`/api/apm/status/server`) + pathname: `/api/apm/status/server` }); } export async function loadAgentStatus() { return callApi({ - pathname: chrome.addBasePath(`/api/apm/status/agent`) + pathname: `/api/apm/status/agent` }); } -export async function loadServiceList({ start, end, query }) { +export async function getEncodedEsQuery(kuery) { + if (!kuery) { + return; + } + + const indexPattern = await getAPMIndexPattern(); + const esFilterQuery = convertKueryToEsQuery(kuery, indexPattern); + return encodeURIComponent(JSON.stringify(esFilterQuery)); +} + +export async function loadServiceList({ start, end, kuery }) { return callApi({ - pathname: chrome.addBasePath(`/api/apm/services`), + pathname: `/api/apm/services`, query: { start, end, - query + esFilterQuery: await getEncodedEsQuery(kuery) } }); } -export async function loadService({ start, end, serviceName }) { +export async function loadServiceDetails({ serviceName, start, end, kuery }) { return callApi({ - pathname: chrome.addBasePath(`/api/apm/services/${serviceName}`), + pathname: `/api/apm/services/${serviceName}`, query: { start, - end + end, + esFilterQuery: await getEncodedEsQuery(kuery) } }); } @@ -90,15 +103,15 @@ export async function loadTransactionList({ serviceName, start, end, + kuery, transactionType }) { return callApi({ - pathname: chrome.addBasePath( - `/api/apm/services/${serviceName}/transactions` - ), + pathname: `/api/apm/services/${serviceName}/transactions`, query: { start, end, + esFilterQuery: await getEncodedEsQuery(kuery), transaction_type: transactionType } }); @@ -108,28 +121,33 @@ export async function loadTransactionDistribution({ serviceName, start, end, - transactionName + transactionName, + kuery }) { return callApi({ - pathname: chrome.addBasePath( - `/api/apm/services/${serviceName}/transactions/distribution` - ), + pathname: `/api/apm/services/${serviceName}/transactions/distribution`, query: { start, end, - transaction_name: transactionName + transaction_name: transactionName, + esFilterQuery: await getEncodedEsQuery(kuery) } }); } -export async function loadSpans({ serviceName, start, end, transactionId }) { +export async function loadSpans({ + serviceName, + start, + end, + transactionId, + kuery +}) { return callApi({ - pathname: chrome.addBasePath( - `/api/apm/services/${serviceName}/transactions/${transactionId}/spans` - ), + pathname: `/api/apm/services/${serviceName}/transactions/${transactionId}/spans`, query: { start, - end + end, + esFilterQuery: await getEncodedEsQuery(kuery) } }); } @@ -138,18 +156,22 @@ export async function loadTransaction({ serviceName, start, end, - transactionId + transactionId, + kuery }) { - const res = await callApi({ - pathname: chrome.addBasePath( - `/api/apm/services/${serviceName}/transactions/${transactionId}` - ), - camelcase: false, - query: { - start, - end + const res = await callApi( + { + pathname: `/api/apm/services/${serviceName}/transactions/${transactionId}`, + query: { + start, + end, + esFilterQuery: await getEncodedEsQuery(kuery) + } + }, + { + camelcase: false } - }); + ); const camelizedRes = camelizeKeys(res); if (res.context) { camelizedRes.context = res.context; @@ -161,16 +183,16 @@ export async function loadCharts({ serviceName, start, end, + kuery, transactionType, transactionName }) { return callApi({ - pathname: chrome.addBasePath( - `/api/apm/services/${serviceName}/transactions/charts` - ), + pathname: `/api/apm/services/${serviceName}/transactions/charts`, query: { start, end, + esFilterQuery: await getEncodedEsQuery(kuery), transaction_type: transactionType, transaction_name: transactionName } @@ -181,40 +203,46 @@ export async function loadErrorGroupList({ serviceName, start, end, + kuery, size, q, sortBy, sortOrder }) { return callApi({ - pathname: chrome.addBasePath(`/api/apm/services/${serviceName}/errors`), + pathname: `/api/apm/services/${serviceName}/errors`, query: { start, end, size, q, sortBy, - sortOrder + sortOrder, + esFilterQuery: await getEncodedEsQuery(kuery) } }); } -export async function loadErrorGroup({ +export async function loadErrorGroupDetails({ serviceName, - errorGroupId, start, - end + end, + kuery, + errorGroupId }) { - const res = await callApi({ - pathname: chrome.addBasePath( - `/api/apm/services/${serviceName}/errors/${errorGroupId}` - ), - camelcase: false, - query: { - start, - end + const res = await callApi( + { + pathname: `/api/apm/services/${serviceName}/errors/${errorGroupId}`, + query: { + start, + end, + esFilterQuery: await getEncodedEsQuery(kuery) + } + }, + { + camelcase: false } - }); + ); const camelizedRes = camelizeKeys(res); if (res.error.context) { camelizedRes.error.context = res.error.context; @@ -226,15 +254,15 @@ export async function loadErrorDistribution({ serviceName, start, end, + kuery, errorGroupId }) { return callApi({ - pathname: chrome.addBasePath( - `/api/apm/services/${serviceName}/errors/${errorGroupId}/distribution` - ), + pathname: `/api/apm/services/${serviceName}/errors/${errorGroupId}/distribution`, query: { start, - end + end, + esFilterQuery: await getEncodedEsQuery(kuery) } }); } @@ -242,7 +270,7 @@ export async function loadErrorDistribution({ export async function createWatch(id, watch) { return callApi({ method: 'PUT', - pathname: chrome.addBasePath(`/api/watcher/watch/${id}`), + pathname: `/api/watcher/watch/${id}`, body: JSON.stringify({ type: 'json', id, watch }) }); } diff --git a/x-pack/plugins/apm/public/store/__jest__/__snapshots__/rootReducer.test.js.snap b/x-pack/plugins/apm/public/store/__jest__/__snapshots__/rootReducer.test.js.snap deleted file mode 100644 index 1117d4dbf5d250..00000000000000 --- a/x-pack/plugins/apm/public/store/__jest__/__snapshots__/rootReducer.test.js.snap +++ /dev/null @@ -1,16 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`root reducer should return default data as state 1`] = ` -Object { - "data": Array [], -} -`; - -exports[`root reducer should return incoming data as state 1`] = ` -Object { - "data": Array [ - "a", - "b", - ], -} -`; diff --git a/x-pack/plugins/apm/public/store/__jest__/apiHelpers.test.js b/x-pack/plugins/apm/public/store/__jest__/apiHelpers.test.js deleted file mode 100644 index a6869976ef1b92..00000000000000 --- a/x-pack/plugins/apm/public/store/__jest__/apiHelpers.test.js +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { createStore } from 'redux'; -import { STATUS } from '../../constants'; -import { - createActionTypes, - createReducer, - createAction, - getKey -} from '../apiHelpers'; - -describe('apiHelpers', () => { - describe('Reducers should not be prone to race conditions', () => { - it('should return the response for the action that was initiated (started loading) last', () => { - const actionTypes = createActionTypes('MY_ACTION'); - const [ACTION_LOADING, ACTION_SUCCESS] = actionTypes; - const reducer = createReducer(actionTypes, {}); - const store = createStore(reducer); - - store.dispatch({ - key: 'first', - type: ACTION_LOADING - }); - - store.dispatch({ - key: 'second', - type: ACTION_LOADING - }); - - store.dispatch({ - key: 'second', - response: 'response from second', - type: ACTION_SUCCESS - }); - - store.dispatch({ - key: 'first', - response: 'response from first', - type: ACTION_SUCCESS - }); - - expect(store.getState()).toEqual({ - data: 'response from second', - key: 'second', - status: 'SUCCESS' - }); - }); - }); - - describe('createActionTypes', () => { - it('should return 3 action types', () => { - expect(createActionTypes('MY_ACTION')).toEqual([ - 'MY_ACTION_LOADING', - 'MY_ACTION_SUCCESS', - 'MY_ACTION_FAILURE' - ]); - }); - }); - - describe('createReducer', () => { - const actionTypes = createActionTypes('MY_ACTION_TYPE'); - const [ - MY_ACTION_TYPE_LOADING, - MY_ACTION_TYPE_SUCCESS, - MY_ACTION_TYPE_FAILURE - ] = actionTypes; - - const initialData = { foo: 'intitial data' }; - - it('should return loading state with initial data', () => { - expect( - createReducer(actionTypes, initialData)(undefined, { - type: MY_ACTION_TYPE_LOADING - }) - ).toEqual({ - status: STATUS.LOADING, - data: { foo: 'intitial data' } - }); - }); - - it('should return loading state with store data', () => { - expect( - createReducer(actionTypes, initialData)( - { data: 'previous data' }, - { - type: MY_ACTION_TYPE_LOADING - } - ) - ).toEqual({ - data: 'previous data', - status: STATUS.LOADING - }); - }); - - it('should return success state', () => { - expect( - createReducer(actionTypes, initialData)(undefined, { - response: { user: 1337 }, - type: MY_ACTION_TYPE_SUCCESS - }) - ).toEqual({ - data: { user: 1337 }, - status: STATUS.SUCCESS - }); - }); - - it('should return failure state', () => { - console.error = jest.fn(); - - expect( - createReducer(actionTypes, initialData)(undefined, { - errorResponse: { msg: 'Something failed :(' }, - type: MY_ACTION_TYPE_FAILURE - }) - ).toEqual({ - error: { msg: 'Something failed :(' }, - data: { foo: 'intitial data' }, - status: STATUS.FAILURE - }); - }); - - it('should return default state', () => { - console.error = jest.fn(); - - expect( - createReducer(actionTypes, initialData)(undefined, { - type: 'NON_MATCHING_TYPE' - }) - ).toEqual({ - data: { foo: 'intitial data' } - }); - }); - }); - - describe('createAction', () => { - const actionTypes = createActionTypes('MY_ACTION_TYPE'); - const [ - MY_ACTION_TYPE_LOADING, - MY_ACTION_TYPE_SUCCESS, - MY_ACTION_TYPE_FAILURE - ] = actionTypes; - - describe('succesful request', () => { - let key; - let dispatchMock; - let apiMock; - let keyArgs; - beforeEach(async () => { - dispatchMock = jest.fn(); - apiMock = jest.fn(() => Promise.resolve('foo')); - keyArgs = { a: 'aa', b: 'bb' }; - key = getKey(keyArgs); - await createAction(actionTypes, apiMock)(keyArgs)(dispatchMock); - }); - - it('should dispatch loading action', () => { - expect(dispatchMock).toHaveBeenCalledWith({ - keyArgs, - key, - type: MY_ACTION_TYPE_LOADING - }); - }); - - it('should call apiMock with keyArgs', () => { - expect(apiMock).toHaveBeenCalledWith(keyArgs); - }); - - it('should dispatch success action', () => { - expect(dispatchMock).toHaveBeenCalledWith({ - keyArgs, - key, - response: 'foo', - type: MY_ACTION_TYPE_SUCCESS - }); - }); - }); - - describe('unsuccesful request', () => { - it('should dispatch error action', async () => { - const dispatchMock = jest.fn(); - const apiMock = jest.fn(() => - Promise.reject(new Error('an error occured :(')) - ); - const keyArgs = { a: 'aa', b: 'bb' }; - const key = getKey(keyArgs); - await createAction(actionTypes, apiMock)(keyArgs)(dispatchMock); - - expect(dispatchMock).toHaveBeenCalledWith({ - keyArgs, - key, - errorResponse: expect.any(Error), - type: MY_ACTION_TYPE_FAILURE - }); - }); - }); - - describe('without arguments', () => { - it('should dispatch success action', async () => { - const dispatchMock = jest.fn(); - const apiMock = jest.fn(() => Promise.resolve('foobar')); - const keyArgs = undefined; - const key = getKey(keyArgs); - await createAction(actionTypes, apiMock)(keyArgs)(dispatchMock); - - expect(dispatchMock).toHaveBeenCalledWith({ - keyArgs: {}, - key, - response: 'foobar', - type: MY_ACTION_TYPE_SUCCESS - }); - }); - }); - }); -}); diff --git a/x-pack/plugins/apm/public/store/__jest__/rootReducer.test.js b/x-pack/plugins/apm/public/store/__jest__/rootReducer.test.js index e0212e94a12738..ed8611f78bdecf 100644 --- a/x-pack/plugins/apm/public/store/__jest__/rootReducer.test.js +++ b/x-pack/plugins/apm/public/store/__jest__/rootReducer.test.js @@ -9,55 +9,13 @@ import reducer from '../rootReducer'; describe('root reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual({ - detailsCharts: { - data: { - dates: [], - responseTimes: {}, - totalHits: 0, - tpmBuckets: [], - weightedAverage: null - } - }, - overviewCharts: { - data: { - dates: [], - responseTimes: {}, - totalHits: 0, - tpmBuckets: [], - weightedAverage: null - } - }, - errorDistribution: { data: { buckets: [], totalHits: 0 } }, - errorGroup: { data: {} }, - errorGroupList: { data: [] }, - license: { - data: { - features: { watcher: { isAvailable: false } }, - license: { isActive: false } - } - }, location: { hash: '', pathname: '', search: '' }, - service: { data: { types: [] } }, - serviceList: { data: [] }, + reactReduxRequest: {}, sorting: { service: { descending: false, key: 'serviceName' }, transaction: { descending: true, key: 'impact' } }, - spans: { data: {} }, - transaction: { data: {} }, - transactionDistribution: { data: { buckets: [], totalHits: 0 } }, - transactionList: { data: [] }, urlParams: {} }); }); - - it('should return incoming data as state', () => { - expect( - reducer({ errorGroupList: { data: ['a', 'b'] } }, {}).errorGroupList - ).toMatchSnapshot(); - }); - - it('should return default data as state', () => { - expect(reducer(undefined, {}).errorGroupList).toMatchSnapshot(); - }); }); diff --git a/x-pack/plugins/apm/public/store/__jest__/serviceList.test.js b/x-pack/plugins/apm/public/store/__jest__/serviceList.test.js deleted file mode 100644 index a5258e0f20a410..00000000000000 --- a/x-pack/plugins/apm/public/store/__jest__/serviceList.test.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - loadServiceList, - SERVICE_LIST_LOADING, - SERVICE_LIST_SUCCESS -} from '../serviceList'; -import { getKey } from '../apiHelpers'; -import fetchMock from 'fetch-mock'; -import response from './services-response.json'; - -describe('loadServiceList', () => { - const key = getKey({ start: 'myStart', end: 'myEnd' }); - const dispatch = jest.fn(); - const matcherName = /\/api\/apm\/services/; - - beforeEach(() => { - fetchMock.get(matcherName, response); - return loadServiceList({ - start: 'myStart', - end: 'myEnd' - })(dispatch); - }); - - afterEach(() => { - fetchMock.restore(); - }); - - it('should make a http request', () => { - expect(fetchMock.lastUrl(matcherName)).toContain( - '/api/apm/services?start=myStart&end=myEnd' - ); - }); - - it('should dispatch SERVICE_LIST_LOADING', () => { - expect(dispatch).toHaveBeenCalledWith({ - keyArgs: { start: 'myStart', end: 'myEnd' }, - type: SERVICE_LIST_LOADING, - key - }); - }); - - it('should dispatch SERVICE_LIST_SUCCESS with http response', () => { - expect(dispatch).toHaveBeenCalledWith({ - keyArgs: { start: 'myStart', end: 'myEnd' }, - response, - type: SERVICE_LIST_SUCCESS, - key - }); - }); -}); diff --git a/x-pack/plugins/apm/public/store/__jest__/services-response.json b/x-pack/plugins/apm/public/store/__jest__/services-response.json deleted file mode 100644 index faa7b3a4319d36..00000000000000 --- a/x-pack/plugins/apm/public/store/__jest__/services-response.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "serviceName": "opbeans-python", - "overallAvg": 163335.74660633484, - "types": ["request"], - "chart": {} - }, - { - "serviceName": "opbeans-backend", - "overallAvg": 370627.24742268043, - "types": ["request", "Brewing Bot"], - "chart": {} - }, - { - "serviceName": "opbeat-stage", - "overallAvg": 6740834.058047493, - "types": ["transaction.celery", "request"], - "chart": {} - } -] diff --git a/x-pack/plugins/apm/public/store/apiHelpers.js b/x-pack/plugins/apm/public/store/apiHelpers.js deleted file mode 100644 index 2d0a09f1299b2b..00000000000000 --- a/x-pack/plugins/apm/public/store/apiHelpers.js +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { STATUS } from '../constants'; -import _ from 'lodash'; -const hash = require('object-hash/index'); - -export function createActionTypes(actionName) { - return [ - `${actionName}_LOADING`, - `${actionName}_SUCCESS`, - `${actionName}_FAILURE` - ]; -} - -export function createReducer(actionTypes, initialData) { - const [LOADING, SUCCESS, FAILURE] = actionTypes; - - return (state, action) => { - switch (action.type) { - case LOADING: - return { - key: action.key, - keyArgs: action.keyArgs, - data: _.get(state, 'data', initialData), - status: STATUS.LOADING - }; - - case SUCCESS: - // This should avoid race-conditions so a slow response doesn't overwrite a newer response (faster) response - if (action.key !== _.get(state, 'key')) { - return state; - } - - return { - key: action.key, - keyArgs: action.keyArgs, - data: action.response, // TODO: rename 'data' to 'response' - status: STATUS.SUCCESS - }; - - case FAILURE: - return { - key: action.key, - keyArgs: action.keyArgs, - data: initialData, - status: STATUS.FAILURE, - error: action.errorResponse // TODO: rename 'error' to 'errorResponse' - }; - default: - return state || { data: initialData }; - } - }; -} - -export function createAction(actionTypes, callApi) { - const [LOADING, SUCCESS, FAILURE] = actionTypes; - - return (keyArgs = {}) => { - return async dispatch => { - const key = hash(keyArgs); - dispatch({ key, keyArgs, type: LOADING }); - - let response; - try { - response = await callApi(keyArgs); - } catch (errorResponse) { - console.error(errorResponse); - return dispatch({ - key, - keyArgs, - errorResponse, - type: FAILURE - }); - } - - try { - return dispatch({ - key, - keyArgs, - response, - type: SUCCESS - }); - } catch (error) { - console.error(error); - } - }; - }; -} - -const hasEmptyProps = obj => _.some(obj, value => value == null); -export const getKey = (obj = {}, notNull = true) => { - return notNull && hasEmptyProps(obj) ? null : hash(obj); -}; diff --git a/x-pack/plugins/apm/public/store/detailsCharts.js b/x-pack/plugins/apm/public/store/detailsCharts.js deleted file mode 100644 index 6d247e08741ec9..00000000000000 --- a/x-pack/plugins/apm/public/store/detailsCharts.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { createSelector } from 'reselect'; -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; -import { getCharts } from './selectors/chartSelectors'; -import { getUrlParams } from './urlParams'; - -const actionTypes = createActionTypes('DETAILS_CHARTS'); - -const INITIAL_DATA = { - totalHits: 0, - dates: [], - responseTimes: {}, - tpmBuckets: [], - weightedAverage: null -}; - -export default createReducer(actionTypes, INITIAL_DATA); -export const loadDetailsCharts = createAction(actionTypes, rest.loadCharts); - -export const getDetailsCharts = createSelector( - getUrlParams, - state => state.detailsCharts, - getCharts -); diff --git a/x-pack/plugins/apm/public/store/errorDistribution.js b/x-pack/plugins/apm/public/store/errorDistribution.js deleted file mode 100644 index cf3ab35fde562d..00000000000000 --- a/x-pack/plugins/apm/public/store/errorDistribution.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; - -const actionTypes = createActionTypes('ERROR_DISTRIBUTION'); -export const [ - ERROR_DISTRIBUTION_LOADING, - ERROR_DISTRIBUTION_SUCCESS, - ERROR_DISTRIBUTION_FAILURE -] = actionTypes; - -const INITIAL_DATA = { buckets: [], totalHits: 0 }; - -export default createReducer(actionTypes, INITIAL_DATA); - -export const loadErrorDistribution = createAction( - actionTypes, - rest.loadErrorDistribution -); - -export function getErrorDistribution(state) { - return state.errorDistribution; -} diff --git a/x-pack/plugins/apm/public/store/errorGroup.js b/x-pack/plugins/apm/public/store/errorGroup.js deleted file mode 100644 index c3728e7a06ad15..00000000000000 --- a/x-pack/plugins/apm/public/store/errorGroup.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; - -const actionTypes = createActionTypes('ERROR_GROUP'); -export const [ - ERROR_GROUP_LOADING, - ERROR_GROUP_SUCCESS, - ERROR_GROUP_FAILURE -] = actionTypes; - -const INITIAL_DATA = {}; - -export default createReducer(actionTypes, INITIAL_DATA); - -export const loadErrorGroup = createAction(actionTypes, rest.loadErrorGroup); - -export function getErrorGroup(state) { - return state.errorGroup; -} diff --git a/x-pack/plugins/apm/public/store/errorGroupList.js b/x-pack/plugins/apm/public/store/errorGroupList.js deleted file mode 100644 index 9b973287c4b853..00000000000000 --- a/x-pack/plugins/apm/public/store/errorGroupList.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; - -const actionTypes = createActionTypes('ERROR_GROUP_LIST'); -export const [ - ERROR_GROUP_LIST_LOADING, - ERROR_GROUP_LIST_SUCCESS, - ERROR_GROUP_LIST_FAILURE -] = actionTypes; - -const INITIAL_DATA = []; -export default createReducer(actionTypes, INITIAL_DATA); - -export const loadErrorGroupList = createAction( - actionTypes, - rest.loadErrorGroupList -); - -export const getErrorGroupList = state => { - return state.errorGroupList; -}; diff --git a/x-pack/plugins/apm/public/store/license.js b/x-pack/plugins/apm/public/store/license.js deleted file mode 100644 index 996a745abc07f8..00000000000000 --- a/x-pack/plugins/apm/public/store/license.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; - -const actionTypes = createActionTypes('LICENSE'); -export const [LICENSE_LOADING, LICENSE_SUCCESS, LICENSE_FAILURE] = actionTypes; - -const INITIAL_DATA = { - features: { watcher: { isAvailable: false } }, - license: { isActive: false } -}; -const license = createReducer(actionTypes, INITIAL_DATA); -export const loadLicense = createAction(actionTypes, rest.loadLicense); - -export default license; diff --git a/x-pack/plugins/apm/public/store/overviewCharts.js b/x-pack/plugins/apm/public/store/overviewCharts.js deleted file mode 100644 index a22ba7ca6fe6b0..00000000000000 --- a/x-pack/plugins/apm/public/store/overviewCharts.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { createSelector } from 'reselect'; -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; -import { getCharts } from './selectors/chartSelectors'; -import { getUrlParams } from './urlParams'; - -const actionTypes = createActionTypes('OVERVIEW_CHARTS'); - -const INITIAL_DATA = { - totalHits: 0, - dates: [], - responseTimes: {}, - tpmBuckets: [], - weightedAverage: null -}; - -export default createReducer(actionTypes, INITIAL_DATA); -export const loadOverviewCharts = createAction(actionTypes, rest.loadCharts); - -export const getOverviewCharts = createSelector( - getUrlParams, - state => state.overviewCharts, - getCharts -); diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/__jest__/serviceList.test.js b/x-pack/plugins/apm/public/store/reactReduxRequest/__jest__/serviceList.test.js new file mode 100644 index 00000000000000..3c700979a9d721 --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/__jest__/serviceList.test.js @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import * as rest from '../../../services/rest'; +import { getServiceList, ServiceListRequest } from '../serviceList'; +import { mountWithStore } from '../../../utils/testHelpers'; + +describe('serviceList', () => { + describe('getServiceList', () => { + it('should return default value when empty', () => { + const state = { reactReduxRequest: {}, sorting: { service: {} } }; + expect(getServiceList(state)).toEqual({ data: [] }); + }); + + it('should return serviceList when not empty', () => { + const state = { + reactReduxRequest: { serviceList: { data: [{ foo: 'bar' }] } }, + sorting: { service: {} } + }; + expect(getServiceList(state)).toEqual({ data: [{ foo: 'bar' }] }); + }); + }); + + describe('ServiceListRequest', () => { + let loadSpy; + let renderSpy; + let wrapper; + + beforeEach(() => { + const state = { + reactReduxRequest: { + serviceList: { status: 'my-status', data: [{ foo: 'bar' }] } + }, + sorting: { service: {} } + }; + + loadSpy = jest.spyOn(rest, 'loadServiceList').mockReturnValue(); + renderSpy = jest.fn().mockReturnValue(
rendered
); + + wrapper = mountWithStore( + , + state + ); + }); + + it('should call render method', () => { + expect(renderSpy).toHaveBeenCalledWith({ + data: [{ foo: 'bar' }], + status: 'my-status' + }); + }); + + it('should call "loadServiceList"', () => { + expect(loadSpy).toHaveBeenCalledWith({ + start: 'myStart', + end: 'myEnd' + }); + }); + + it('should render component', () => { + expect(wrapper.html()).toEqual('
rendered
'); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/detailsCharts.js b/x-pack/plugins/apm/public/store/reactReduxRequest/detailsCharts.js new file mode 100644 index 00000000000000..d7648a73bbcf8e --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/detailsCharts.js @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { createSelector } from 'reselect'; +import { getCharts } from '../selectors/chartSelectors'; +import { getUrlParams } from '../urlParams'; +import { Request } from 'react-redux-request'; +import { loadCharts } from '../../services/rest'; +import { withInitialData } from './helpers'; + +const ID = 'detailsCharts'; +const INITIAL_DATA = { + totalHits: 0, + dates: [], + responseTimes: {}, + tpmBuckets: [], + weightedAverage: null +}; + +export const getDetailsCharts = createSelector( + getUrlParams, + state => withInitialData(state.reactReduxRequest[ID], INITIAL_DATA), + (urlParams, detailCharts) => { + return { + ...detailCharts, + data: getCharts(urlParams, detailCharts.data) + }; + } +); + +export function DetailsChartsRequest({ urlParams, render }) { + const { + serviceName, + start, + end, + transactionType, + transactionName, + kuery + } = urlParams; + + if (!(serviceName && start && end && transactionType && transactionName)) { + return null; + } + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/errorDistribution.js b/x-pack/plugins/apm/public/store/reactReduxRequest/errorDistribution.js new file mode 100644 index 00000000000000..a2cf4899f1a803 --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/errorDistribution.js @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { Request } from 'react-redux-request'; +import { loadErrorDistribution } from '../../services/rest'; +import { withInitialData } from './helpers'; + +const ID = 'errorDistribution'; +const INITIAL_DATA = { buckets: [], totalHits: 0 }; + +export function getErrorDistribution(state) { + return withInitialData(state.reactReduxRequest[ID], INITIAL_DATA); +} + +export function ErrorDistributionRequest({ urlParams, render }) { + const { serviceName, start, end, errorGroupId, kuery } = urlParams; + + if (!(serviceName, start, end, errorGroupId)) { + return null; + } + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroup.js b/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroup.js new file mode 100644 index 00000000000000..d4fef9406725db --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroup.js @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { withInitialData } from './helpers'; +import { Request } from 'react-redux-request'; +import { loadErrorGroupDetails } from '../../services/rest'; + +const ID = 'errorGroupDetails'; +const INITIAL_DATA = {}; + +export function getErrorGroupDetails(state) { + return withInitialData(state.reactReduxRequest[ID], INITIAL_DATA); +} + +export function ErrorGroupDetailsRequest({ urlParams, render }) { + const { serviceName, errorGroupId, start, end, kuery } = urlParams; + + if (!(serviceName && start && end && errorGroupId)) { + return null; + } + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroupList.js b/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroupList.js new file mode 100644 index 00000000000000..a0c2ca45a5f7bb --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/errorGroupList.js @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { withInitialData } from './helpers'; +import { Request } from 'react-redux-request'; +import { loadErrorGroupList } from '../../services/rest'; + +const ID = 'errorGroupList'; +const INITIAL_DATA = []; + +export function getErrorGroupList(state) { + return withInitialData(state.reactReduxRequest[ID], INITIAL_DATA); +} + +export function ErrorGroupDetailsRequest({ urlParams, render }) { + const { serviceName, start, end, q, sortBy, sortOrder, kuery } = urlParams; + + if (!(serviceName && start && end)) { + return null; + } + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/helpers.js b/x-pack/plugins/apm/public/store/reactReduxRequest/helpers.js new file mode 100644 index 00000000000000..cbede56bc117f6 --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/helpers.js @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export function withInitialData(state = {}, initialData) { + return { + ...state, + data: state.data || initialData + }; +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/license.js b/x-pack/plugins/apm/public/store/reactReduxRequest/license.js new file mode 100644 index 00000000000000..8624daf2d6fa5c --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/license.js @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import { withInitialData } from './helpers'; +import { Request } from 'react-redux-request'; +import { loadLicense } from '../../services/rest'; + +const ID = 'license'; +const INITIAL_DATA = { + features: { watcher: { isAvailable: false } }, + license: { isActive: false } +}; + +export function getLicense(state) { + return withInitialData(state.reactReduxRequest[ID], INITIAL_DATA); +} + +export function LicenceRequest({ render }) { + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/overviewCharts.js b/x-pack/plugins/apm/public/store/reactReduxRequest/overviewCharts.js new file mode 100644 index 00000000000000..f3d0a87dc35d16 --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/overviewCharts.js @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { createSelector } from 'reselect'; +import { getCharts } from '../selectors/chartSelectors'; +import { getUrlParams } from '../urlParams'; +import { Request } from 'react-redux-request'; +import { loadCharts } from '../../services/rest'; +import { withInitialData } from './helpers'; + +const ID = 'overviewCharts'; +const INITIAL_DATA = { + totalHits: 0, + dates: [], + responseTimes: {}, + tpmBuckets: [], + weightedAverage: null +}; + +export const getOverviewCharts = createSelector( + getUrlParams, + state => withInitialData(state.reactReduxRequest[ID], INITIAL_DATA), + (urlParams, overviewCharts) => { + return { + ...overviewCharts, + data: getCharts(urlParams, overviewCharts.data) + }; + } +); + +export function OverviewChartsRequest({ urlParams, render }) { + const { serviceName, start, end, transactionType, kuery } = urlParams; + + if (!(serviceName && start && end && transactionType)) { + return null; + } + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/serviceDetails.js b/x-pack/plugins/apm/public/store/reactReduxRequest/serviceDetails.js new file mode 100644 index 00000000000000..dca0f064e80d0c --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/serviceDetails.js @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import { withInitialData } from './helpers'; +import { Request } from 'react-redux-request'; +import { loadServiceDetails } from '../../services/rest'; + +const ID = 'serviceDetails'; +const INITIAL_DATA = { types: [] }; + +export function getServiceDetails(state) { + return withInitialData(state.reactReduxRequest[ID], INITIAL_DATA); +} + +export function getDefaultTransactionType(state) { + const types = _.get(state.reactReduxRequest[ID], 'data.types'); + return _.first(types); +} + +export function ServiceDetailsRequest({ urlParams, render }) { + const { serviceName, start, end, kuery } = urlParams; + + if (!(serviceName && start && end)) { + return null; + } + + return ( + + ); +} + +ServiceDetailsRequest.propTypes = { + urlParams: PropTypes.object.isRequired, + render: PropTypes.func.isRequired +}; diff --git a/x-pack/plugins/apm/public/store/serviceList.js b/x-pack/plugins/apm/public/store/reactReduxRequest/serviceList.js similarity index 52% rename from x-pack/plugins/apm/public/store/serviceList.js rename to x-pack/plugins/apm/public/store/reactReduxRequest/serviceList.js index 738996c3851f13..3dccb542f10513 100644 --- a/x-pack/plugins/apm/public/store/serviceList.js +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/serviceList.js @@ -4,27 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import * as rest from '../services/rest'; +import React from 'react'; import orderBy from 'lodash.orderby'; import { createSelector } from 'reselect'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; - -const actionTypes = createActionTypes('SERVICE_LIST'); -export const [ - SERVICE_LIST_LOADING, - SERVICE_LIST_SUCCESS, - SERVICE_LIST_FAILURE -] = actionTypes; +import { loadServiceList } from '../../services/rest'; +import { Request } from 'react-redux-request'; +import { withInitialData } from './helpers'; +const ID = 'serviceList'; const INITIAL_DATA = []; -const serviceList = createReducer(actionTypes, INITIAL_DATA); - -export const loadServiceList = createAction(actionTypes, rest.loadServiceList); - -// SELECTORS export const getServiceList = createSelector( - state => state.serviceList, + state => withInitialData(state.reactReduxRequest[ID], INITIAL_DATA), state => state.sorting.service, (serviceList, serviceSorting) => { const { key: sortKey, descending } = serviceSorting; @@ -36,4 +27,20 @@ export const getServiceList = createSelector( } ); -export default serviceList; +export function ServiceListRequest({ urlParams, render }) { + const { start, end, kuery } = urlParams; + + if (!(start && end)) { + return null; + } + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/spans.js b/x-pack/plugins/apm/public/store/reactReduxRequest/spans.js new file mode 100644 index 00000000000000..b65f8815b284b7 --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/spans.js @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { withInitialData } from './helpers'; +import { Request } from 'react-redux-request'; +import { loadSpans } from '../../services/rest'; + +const ID = 'spans'; +const INITIAL_DATA = {}; + +export function getSpans(state) { + return withInitialData(state.reactReduxRequest[ID], INITIAL_DATA); +} + +export function SpansRequest({ urlParams, render }) { + const { serviceName, start, end, transactionId, kuery } = urlParams; + + if (!(serviceName && start && end && transactionId)) { + return null; + } + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDetails.js b/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDetails.js new file mode 100644 index 00000000000000..5de795f7fd46eb --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDetails.js @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { withInitialData } from './helpers'; +import { Request } from 'react-redux-request'; +import { loadTransaction } from '../../services/rest'; + +const ID = 'transactionDetails'; +const INITIAL_DATA = {}; + +export function getTransactionDetails(state) { + return withInitialData(state.reactReduxRequest[ID], INITIAL_DATA); +} + +export function TransactionDetailsRequest({ urlParams, render }) { + const { serviceName, start, end, transactionId, kuery } = urlParams; + + if (!(serviceName && start && end && transactionId)) { + return null; + } + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDistribution.js b/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDistribution.js new file mode 100644 index 00000000000000..789662707cfcf0 --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/transactionDistribution.js @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { withInitialData } from './helpers'; +import { Request } from 'react-redux-request'; +import { loadTransactionDistribution } from '../../services/rest'; + +const ID = 'transactionDistribution'; +const INITIAL_DATA = { buckets: [], totalHits: 0 }; + +export function getTransactionDistribution(state) { + return withInitialData(state.reactReduxRequest[ID], INITIAL_DATA); +} + +export function getDefaultTransactionId(state) { + const distribution = getTransactionDistribution(state); + return distribution.data.defaultTransactionId; +} + +export function TransactionDistributionRequest({ urlParams, render }) { + const { serviceName, start, end, transactionName, kuery } = urlParams; + + if (!(serviceName && start && end && transactionName)) { + return null; + } + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/reactReduxRequest/transactionList.js b/x-pack/plugins/apm/public/store/reactReduxRequest/transactionList.js new file mode 100644 index 00000000000000..de3894bd9e8909 --- /dev/null +++ b/x-pack/plugins/apm/public/store/reactReduxRequest/transactionList.js @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import orderBy from 'lodash.orderby'; +import { createSelector } from 'reselect'; +import { Request } from 'react-redux-request'; +import { loadTransactionList } from '../../services/rest'; +import { withInitialData } from './helpers'; + +const ID = 'transactionList'; +const INITIAL_DATA = []; + +export const getTransactionList = createSelector( + state => withInitialData(state.reactReduxRequest[ID], INITIAL_DATA), + state => state.sorting.transaction, + (transactionList = {}, transactionSorting) => { + const { key: sortKey, descending } = transactionSorting; + + return { + ...transactionList, + data: orderBy(transactionList.data, sortKey, descending ? 'desc' : 'asc') + }; + } +); + +export function TransactionListRequest({ urlParams, render }) { + const { serviceName, start, end, transactionType, kuery } = urlParams; + + if (!(serviceName && start && end && transactionType)) { + return null; + } + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/store/rootReducer.js b/x-pack/plugins/apm/public/store/rootReducer.js index c75516cca27a98..34450084a0531e 100644 --- a/x-pack/plugins/apm/public/store/rootReducer.js +++ b/x-pack/plugins/apm/public/store/rootReducer.js @@ -5,39 +5,16 @@ */ import { combineReducers } from 'redux'; - -import detailsCharts from './detailsCharts'; -import errorDistribution from './errorDistribution'; -import errorGroup from './errorGroup'; -import errorGroupList from './errorGroupList'; -import license from './license'; import location from './location'; -import overviewCharts from './overviewCharts'; -import service from './service'; -import serviceList from './serviceList'; import sorting from './sorting'; -import spans from './spans'; -import transaction from './transaction'; -import transactionDistribution from './transactionDistribution'; -import transactionList from './transactionList'; import urlParams from './urlParams'; +import { reducer } from 'react-redux-request'; const rootReducer = combineReducers({ - detailsCharts, - errorDistribution, - errorGroup, - errorGroupList, - license, location, - overviewCharts, - service, - serviceList, sorting, - spans, - transaction, - transactionDistribution, - transactionList, - urlParams + urlParams, + reactReduxRequest: reducer }); export default rootReducer; diff --git a/x-pack/plugins/apm/public/store/selectors/chartSelectors.js b/x-pack/plugins/apm/public/store/selectors/chartSelectors.js index 16a67655c696c2..1a30f9ce9bc3f1 100644 --- a/x-pack/plugins/apm/public/store/selectors/chartSelectors.js +++ b/x-pack/plugins/apm/public/store/selectors/chartSelectors.js @@ -34,23 +34,19 @@ export const getEmptySerie = memoize( export function getCharts(urlParams, charts) { const { start, end, transactionType } = urlParams; - const chartsData = charts.data; - const noHits = chartsData.totalHits === 0; + const noHits = charts.totalHits === 0; const tpmSeries = noHits ? getEmptySerie(start, end) - : getTpmSeries(chartsData, transactionType); + : getTpmSeries(charts, transactionType); const responseTimeSeries = noHits ? getEmptySerie(start, end) - : getResponseTimeSeries(chartsData); + : getResponseTimeSeries(charts); return { - ...charts, - data: { - noHits, - tpmSeries, - responseTimeSeries - } + noHits, + tpmSeries, + responseTimeSeries }; } diff --git a/x-pack/plugins/apm/public/store/service.js b/x-pack/plugins/apm/public/store/service.js deleted file mode 100644 index 40267cecd3a1e2..00000000000000 --- a/x-pack/plugins/apm/public/store/service.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import _ from 'lodash'; -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; - -const actionTypes = createActionTypes('SERVICE'); -export const [SERVICE_LOADING, SERVICE_SUCCESS, SERVICE_FAILURE] = actionTypes; - -const INITIAL_DATA = { types: [] }; -const service = createReducer(actionTypes, INITIAL_DATA); -export const loadService = createAction(actionTypes, rest.loadService); - -export function getService(state) { - return state.service; -} - -export function getDefaultTransactionType(state) { - const types = _.get(state.service, 'data.types'); - return _.first(types); -} - -export default service; diff --git a/x-pack/plugins/apm/public/store/spans.js b/x-pack/plugins/apm/public/store/spans.js deleted file mode 100644 index 082093b5375c1e..00000000000000 --- a/x-pack/plugins/apm/public/store/spans.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; - -const actionTypes = createActionTypes('SPANS'); -export const [SPANS_LOADING, SPANS_SUCCESS, SPANS_FAILURE] = actionTypes; - -const INITIAL_DATA = {}; -const spans = createReducer(actionTypes, INITIAL_DATA); -export const loadSpans = createAction(actionTypes, rest.loadSpans); - -export function getSpans(state) { - return state.spans; -} - -export default spans; diff --git a/x-pack/plugins/apm/public/store/transaction.js b/x-pack/plugins/apm/public/store/transaction.js deleted file mode 100644 index 45e1c2a4f5c885..00000000000000 --- a/x-pack/plugins/apm/public/store/transaction.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; - -const actionTypes = createActionTypes('TRANSACTION'); -export const [ - TRANSACTION_LOADING, - TRANSACTION_SUCCESS, - TRANSACTION_FAILURE -] = actionTypes; - -const INITIAL_DATA = {}; -const transaction = createReducer(actionTypes, INITIAL_DATA); - -export const loadTransaction = createAction(actionTypes, rest.loadTransaction); - -export function getTransaction(state) { - return state.transaction; -} - -export default transaction; diff --git a/x-pack/plugins/apm/public/store/transactionDistribution.js b/x-pack/plugins/apm/public/store/transactionDistribution.js deleted file mode 100644 index df3ae9f69f680c..00000000000000 --- a/x-pack/plugins/apm/public/store/transactionDistribution.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; - -const actionTypes = createActionTypes('TRANSACTION_DISTRIBUTION'); -export const [ - TRANSACTION_DISTRIBUTION_LOADING, - TRANSACTION_DISTRIBUTION_SUCCESS, - TRANSACTION_DISTRIBUTION_FAILURE -] = actionTypes; - -const INITIAL_DATA = { buckets: [], totalHits: 0 }; -const transactionDistribution = createReducer(actionTypes, INITIAL_DATA); - -export const loadTransactionDistribution = createAction( - actionTypes, - rest.loadTransactionDistribution -); - -export function getTransactionDistribution(state) { - return state.transactionDistribution; -} - -export function getDefaultTransactionId(state) { - const _distribution = getTransactionDistribution(state); - return _distribution.data.defaultTransactionId; -} - -export default transactionDistribution; diff --git a/x-pack/plugins/apm/public/store/transactionList.js b/x-pack/plugins/apm/public/store/transactionList.js deleted file mode 100644 index 0a657edb94e1e0..00000000000000 --- a/x-pack/plugins/apm/public/store/transactionList.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import orderBy from 'lodash.orderby'; -import { createSelector } from 'reselect'; -import * as rest from '../services/rest'; -import { createActionTypes, createAction, createReducer } from './apiHelpers'; - -const actionTypes = createActionTypes('TRANSACTIONS_LIST'); -export const [ - TRANSACTIONS_LIST_LOADING, - TRANSACTIONS_LIST_SUCCESS, - TRANSACTIONS_LIST_FAILURE -] = actionTypes; - -const INITIAL_DATA = []; -const transactionList = createReducer(actionTypes, INITIAL_DATA); - -export const loadTransactionList = createAction( - actionTypes, - rest.loadTransactionList -); - -export const getTransactionList = createSelector( - state => state.transactionList, - state => state.sorting.transaction, - (transactionList, transactionSorting) => { - const { key: sortKey, descending } = transactionSorting; - - return { - ...transactionList, - data: orderBy(transactionList.data, sortKey, descending ? 'desc' : 'asc') - }; - } -); - -export default transactionList; diff --git a/x-pack/plugins/apm/public/store/urlParams.js b/x-pack/plugins/apm/public/store/urlParams.js index cf3db3a7e43e6d..c28f80bfda340b 100644 --- a/x-pack/plugins/apm/public/store/urlParams.js +++ b/x-pack/plugins/apm/public/store/urlParams.js @@ -8,8 +8,8 @@ import _ from 'lodash'; import { createSelector } from 'reselect'; import { LOCATION_UPDATE } from './location'; import { toQuery, legacyDecodeURIComponent } from '../utils/url'; -import { getDefaultTransactionId } from './transactionDistribution'; -import { getDefaultTransactionType } from './service'; +import { getDefaultTransactionId } from './reactReduxRequest/transactionDistribution'; +import { getDefaultTransactionType } from './reactReduxRequest/serviceDetails'; // ACTION TYPES export const TIMEPICKER_UPDATE = 'TIMEPICKER_UPDATE'; @@ -39,7 +39,8 @@ function urlParams(state = {}, action) { page, sortBy, sortOrder, - q + q, + kuery } = toQuery(action.location.search); return { @@ -53,6 +54,7 @@ function urlParams(state = {}, action) { transactionId, detailTab, spanId: toNumber(spanId), + kuery: legacyDecodeURIComponent(kuery), // path params serviceName, diff --git a/x-pack/plugins/apm/public/utils/__test__/__snapshots__/url.test.js.snap b/x-pack/plugins/apm/public/utils/__test__/__snapshots__/url.test.js.snap index c4e52ea41330bd..4e5e7a8c64042c 100644 --- a/x-pack/plugins/apm/public/utils/__test__/__snapshots__/url.test.js.snap +++ b/x-pack/plugins/apm/public/utils/__test__/__snapshots__/url.test.js.snap @@ -12,9 +12,9 @@ exports[`KibanaLinkComponent should render correct markup 1`] = ` exports[`RelativeLinkComponent should render correct markup 1`] = `
- Errors + Go to Discover `; diff --git a/x-pack/plugins/apm/public/utils/__test__/url.test.js b/x-pack/plugins/apm/public/utils/__test__/url.test.js index ba8ae47603ebe3..abb549a5d283ac 100644 --- a/x-pack/plugins/apm/public/utils/__test__/url.test.js +++ b/x-pack/plugins/apm/public/utils/__test__/url.test.js @@ -5,8 +5,9 @@ */ import React from 'react'; -import { MemoryRouter } from 'react-router-dom'; +import { Router } from 'react-router-dom'; import { mount } from 'enzyme'; +import createHistory from 'history/createMemoryHistory'; import { toQuery, @@ -48,35 +49,58 @@ describe('fromQuery', () => { }); describe('RelativeLinkComponent', () => { + let history; let wrapper; beforeEach(() => { + history = createHistory(); + history.location = { + ...history.location, + pathname: '/opbeans-node/transactions', + search: '?foo=bar' + }; + wrapper = mount( - + - Errors + Go to Discover - + ); }); it('should have correct url', () => { expect(wrapper.find('a').prop('href')).toBe( - '/opbeans-backend/errors?_g=(refreshInterval:(display:Off,pause:!f,value:0),time:(from:now-2y,mode:quick,to:now))' + '/opbeans-node/errors?foo=bar&foo2=bar2' ); }); it('should render correct markup', () => { expect(toJson(wrapper)).toMatchSnapshot(); }); + + it('should have initial location', () => { + expect(history.location).toEqual( + expect.objectContaining({ + pathname: '/opbeans-node/transactions', + search: '?foo=bar' + }) + ); + }); + + it('should update location on click', () => { + wrapper.simulate('click', { button: 0 }); + expect(history.location).toEqual( + expect.objectContaining({ + pathname: '/opbeans-node/errors', + search: '?foo=bar&foo2=bar2' + }) + ); + }); }); describe('KibanaLinkComponent', () => { diff --git a/x-pack/plugins/apm/public/utils/documentation.js b/x-pack/plugins/apm/public/utils/documentation.js index a608e290130497..cf285d064e9cf6 100644 --- a/x-pack/plugins/apm/public/utils/documentation.js +++ b/x-pack/plugins/apm/public/utils/documentation.js @@ -5,8 +5,9 @@ */ import { get } from 'lodash'; +import { metadata } from 'ui/metadata'; -const STACK_VERSION = '6.2'; +const STACK_VERSION = metadata.branch; const DOCS_ROOT = 'https://www.elastic.co/guide/en/apm'; // diff --git a/x-pack/plugins/apm/public/utils/testHelpers.js b/x-pack/plugins/apm/public/utils/testHelpers.js index 4b2b17d29b985f..756f7f41305a43 100644 --- a/x-pack/plugins/apm/public/utils/testHelpers.js +++ b/x-pack/plugins/apm/public/utils/testHelpers.js @@ -51,6 +51,21 @@ export function mountWithRouterAndStore( return mount(Component, options); } +export function mountWithStore(Component, storeState = {}) { + const store = createMockStore(storeState); + + const options = { + context: { + store + }, + childContextTypes: { + store: PropTypes.object.isRequired + } + }; + + return mount(Component, options); +} + export function mockMoment() { // avoid timezone issues jest.spyOn(moment.prototype, 'format').mockImplementation(function() { diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.js b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.js index 903aecba6422b2..a8f7450e024b61 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.js +++ b/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.js @@ -7,7 +7,7 @@ import { SERVICE_NAME, ERROR_GROUP_ID } from '../../../../common/constants'; export async function getBuckets({ serviceName, groupId, bucketSize, setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const params = { index: config.get('xpack.apm.indexPattern'), @@ -16,6 +16,8 @@ export async function getBuckets({ serviceName, groupId, bucketSize, setup }) { query: { bool: { filter: [ + { term: { [SERVICE_NAME]: serviceName } }, + { term: { [ERROR_GROUP_ID]: groupId } }, { range: { '@timestamp': { @@ -24,9 +26,7 @@ export async function getBuckets({ serviceName, groupId, bucketSize, setup }) { format: 'epoch_millis' } } - }, - { term: { [ERROR_GROUP_ID]: groupId } }, - { term: { [SERVICE_NAME]: serviceName } } + } ] } }, @@ -46,6 +46,10 @@ export async function getBuckets({ serviceName, groupId, bucketSize, setup }) { } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + const resp = await client('search', params); const buckets = resp.aggregations.distribution.buckets.map(bucket => ({ diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_group.js b/x-pack/plugins/apm/server/lib/errors/get_error_group.js index 0f3ce1ca82e9cb..409b389dafbfa6 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_error_group.js +++ b/x-pack/plugins/apm/server/lib/errors/get_error_group.js @@ -8,7 +8,7 @@ import { SERVICE_NAME, ERROR_GROUP_ID } from '../../../common/constants'; import { get } from 'lodash'; export async function getErrorGroup({ serviceName, groupId, setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const params = { index: config.get('xpack.apm.indexPattern'), @@ -39,6 +39,10 @@ export async function getErrorGroup({ serviceName, groupId, setup }) { } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + const resp = await client('search', params); return { diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_groups.js b/x-pack/plugins/apm/server/lib/errors/get_error_groups.js index 24e15f5d5a96dc..28d6afb059bc4c 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_error_groups.js +++ b/x-pack/plugins/apm/server/lib/errors/get_error_groups.js @@ -22,7 +22,7 @@ export async function getErrorGroups({ sortOrder = 'desc', setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const params = { index: config.get('xpack.apm.indexPattern'), @@ -73,6 +73,10 @@ export async function getErrorGroups({ } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + // sort buckets by last occurence of error if (sortBy === 'latestOccurrenceAt') { params.body.aggs.error_groups.terms.order = { diff --git a/x-pack/plugins/apm/server/lib/helpers/calculate_auto.js b/x-pack/plugins/apm/server/lib/helpers/get_bucket_size/calculate_auto.js similarity index 100% rename from x-pack/plugins/apm/server/lib/helpers/calculate_auto.js rename to x-pack/plugins/apm/server/lib/helpers/get_bucket_size/calculate_auto.js diff --git a/x-pack/plugins/apm/server/lib/helpers/get_bucket_size.js b/x-pack/plugins/apm/server/lib/helpers/get_bucket_size/index.js similarity index 100% rename from x-pack/plugins/apm/server/lib/helpers/get_bucket_size.js rename to x-pack/plugins/apm/server/lib/helpers/get_bucket_size/index.js diff --git a/x-pack/plugins/apm/server/lib/helpers/unit_to_seconds.js b/x-pack/plugins/apm/server/lib/helpers/get_bucket_size/unit_to_seconds.js similarity index 100% rename from x-pack/plugins/apm/server/lib/helpers/unit_to_seconds.js rename to x-pack/plugins/apm/server/lib/helpers/get_bucket_size/unit_to_seconds.js diff --git a/x-pack/plugins/apm/server/lib/helpers/input_validation.js b/x-pack/plugins/apm/server/lib/helpers/input_validation.js new file mode 100644 index 00000000000000..863af18b946151 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/helpers/input_validation.js @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import Joi from 'joi'; +export const dateValidation = Joi.alternatives() + .try(Joi.date().iso(), Joi.number()) + .required(); + +export const withDefaultValidators = (validators = {}) => { + return Joi.object().keys({ + start: dateValidation, + end: dateValidation, + esFilterQuery: Joi.string().allow(''), + ...validators + }); +}; diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.js b/x-pack/plugins/apm/server/lib/helpers/setup_request.js index 5e7c4e9d424b4b..db63a02075cf80 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.js +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.js @@ -6,12 +6,17 @@ import moment from 'moment'; +function decodeEsQuery(esQuery) { + return esQuery ? JSON.parse(decodeURIComponent(esQuery)) : null; +} + export function setupRequest(req, reply) { const cluster = req.server.plugins.elasticsearch.getCluster('data'); const setup = { start: moment.utc(req.query.start).valueOf(), end: moment.utc(req.query.end).valueOf(), + esFilterQuery: decodeEsQuery(req.query.esFilterQuery), client: cluster.callWithRequest.bind(null, req), config: req.server.config() }; diff --git a/x-pack/plugins/apm/server/lib/services/get_service.js b/x-pack/plugins/apm/server/lib/services/get_service.js index e25753eefcd7ce..f7515a5dedcd04 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service.js +++ b/x-pack/plugins/apm/server/lib/services/get_service.js @@ -12,7 +12,7 @@ import { } from '../../../common/constants'; export async function getService({ serviceName, setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const params = { index: config.get('xpack.apm.indexPattern'), @@ -45,6 +45,10 @@ export async function getService({ serviceName, setup }) { } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + const resp = await client('search', params); return { diff --git a/x-pack/plugins/apm/server/lib/services/get_services.js b/x-pack/plugins/apm/server/lib/services/get_services.js index fa5380b4029c04..47648e0d638a87 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services.js +++ b/x-pack/plugins/apm/server/lib/services/get_services.js @@ -13,7 +13,7 @@ import { import { get } from 'lodash'; export async function getServices({ setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const params = { index: config.get('xpack.apm.indexPattern'), @@ -25,16 +25,8 @@ export async function getServices({ setup }) { { bool: { should: [ - { - term: { - [PROCESSOR_EVENT]: 'transaction' - } - }, - { - term: { - [PROCESSOR_EVENT]: 'error' - } - } + { term: { [PROCESSOR_EVENT]: 'transaction' } }, + { term: { [PROCESSOR_EVENT]: 'error' } } ] } }, @@ -72,6 +64,10 @@ export async function getServices({ setup }) { } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + const resp = await client('search', params); const buckets = get(resp.aggregations, 'services.buckets', []); diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data.js b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data.js index aff30945c7c443..835808d63746ac 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data.js +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data.js @@ -21,7 +21,7 @@ export async function getTimeseriesData({ transactionName, setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const { intervalString, bucketSize } = getBucketSize(start, end, 'auto'); const params = { @@ -94,6 +94,10 @@ export async function getTimeseriesData({ } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + if (transactionName) { params.body.query.bool.must = [ { term: { [`${TRANSACTION_NAME}.keyword`]: transactionName } } diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.js b/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.js index 97964532dbf38e..90a5950c5f7a26 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.js +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/calculate_bucket_size.js @@ -15,7 +15,7 @@ export async function calculateBucketSize({ transactionName, setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const params = { index: config.get('xpack.apm.indexPattern'), @@ -24,6 +24,8 @@ export async function calculateBucketSize({ query: { bool: { filter: [ + { term: { [SERVICE_NAME]: serviceName } }, + { term: { [`${TRANSACTION_NAME}.keyword`]: transactionName } }, { range: { '@timestamp': { @@ -32,9 +34,7 @@ export async function calculateBucketSize({ format: 'epoch_millis' } } - }, - { term: { [`${TRANSACTION_NAME}.keyword`]: transactionName } }, - { term: { [SERVICE_NAME]: serviceName } } + } ] } }, @@ -48,6 +48,10 @@ export async function calculateBucketSize({ } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + const resp = await client('search', params); const minBucketSize = config.get('xpack.apm.minimumBucketSize'); const bucketTargetCount = config.get('xpack.apm.bucketTargetCount'); diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets.js b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets.js index 650952d8d87ee9..56e275cc372c0d 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets.js +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets.js @@ -19,7 +19,7 @@ export async function getBuckets({ bucketSize = 100, setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const bucketTargetCount = config.get('xpack.apm.bucketTargetCount'); @@ -30,6 +30,8 @@ export async function getBuckets({ query: { bool: { filter: [ + { term: { [SERVICE_NAME]: serviceName } }, + { term: { [`${TRANSACTION_NAME}.keyword`]: transactionName } }, { range: { '@timestamp': { @@ -38,9 +40,7 @@ export async function getBuckets({ format: 'epoch_millis' } } - }, - { term: { [SERVICE_NAME]: serviceName } }, - { term: { [`${TRANSACTION_NAME}.keyword`]: transactionName } } + } ], should: [{ term: { [TRANSACTION_SAMPLED]: true } }] } @@ -69,6 +69,10 @@ export async function getBuckets({ } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + const resp = await client('search', params); const buckets = resp.aggregations.distribution.buckets.map(bucket => { diff --git a/x-pack/plugins/apm/server/lib/transactions/get_top_transactions.js b/x-pack/plugins/apm/server/lib/transactions/get_top_transactions.js index 649fefa2601869..f0fc70a58d3e44 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_top_transactions.js +++ b/x-pack/plugins/apm/server/lib/transactions/get_top_transactions.js @@ -19,7 +19,7 @@ export async function getTopTransactions({ serviceName, setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const duration = moment.duration(end - start); const minutes = duration.asMinutes(); @@ -75,6 +75,10 @@ export async function getTopTransactions({ } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + const resp = await client('search', params); const buckets = get(resp, 'aggregations.transactions.buckets', []); const results = buckets.map(bucket => { diff --git a/x-pack/plugins/apm/server/lib/transactions/get_transaction.js b/x-pack/plugins/apm/server/lib/transactions/get_transaction.js index 0fb2a8c6f180e2..2132a4602890d2 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_transaction.js +++ b/x-pack/plugins/apm/server/lib/transactions/get_transaction.js @@ -8,7 +8,7 @@ import { TRANSACTION_ID, PROCESSOR_EVENT } from '../../../common/constants'; import { get } from 'lodash'; async function getTransaction({ transactionId, setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const params = { index: config.get('xpack.apm.indexPattern'), @@ -33,6 +33,11 @@ async function getTransaction({ transactionId, setup }) { } } }; + + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + const resp = await client('search', params); return get(resp, 'hits.hits[0]._source', {}); } diff --git a/x-pack/plugins/apm/server/lib/transactions/get_transaction_duration.js b/x-pack/plugins/apm/server/lib/transactions/get_transaction_duration.js index 4f3ebbae795fd1..a3ec24cba78345 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_transaction_duration.js +++ b/x-pack/plugins/apm/server/lib/transactions/get_transaction_duration.js @@ -12,7 +12,7 @@ import { } from '../../../common/constants'; export async function getTransactionDuration({ transactionId, setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const params = { index: config.get('xpack.apm.indexPattern'), @@ -39,6 +39,10 @@ export async function getTransactionDuration({ transactionId, setup }) { } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + const resp = await client('search', params); return get(resp, `hits.hits[0]._source.${TRANSACTION_DURATION}`); } diff --git a/x-pack/plugins/apm/server/lib/transactions/spans/get_spans.js b/x-pack/plugins/apm/server/lib/transactions/spans/get_spans.js index 6f9dcc8785163b..851d1478512a64 100644 --- a/x-pack/plugins/apm/server/lib/transactions/spans/get_spans.js +++ b/x-pack/plugins/apm/server/lib/transactions/spans/get_spans.js @@ -12,7 +12,7 @@ import { } from '../../../../common/constants'; async function getSpans({ transactionId, setup }) { - const { start, end, client, config } = setup; + const { start, end, esFilterQuery, client, config } = setup; const params = { index: config.get('xpack.apm.indexPattern'), @@ -21,6 +21,8 @@ async function getSpans({ transactionId, setup }) { query: { bool: { filter: [ + { term: { [TRANSACTION_ID]: transactionId } }, + { term: { [PROCESSOR_EVENT]: 'span' } }, { range: { '@timestamp': { @@ -29,9 +31,7 @@ async function getSpans({ transactionId, setup }) { format: 'epoch_millis' } } - }, - { term: { [TRANSACTION_ID]: transactionId } }, - { term: { [PROCESSOR_EVENT]: 'span' } } + } ] } }, @@ -47,6 +47,10 @@ async function getSpans({ transactionId, setup }) { } }; + if (esFilterQuery) { + params.body.query.bool.filter.push(esFilterQuery); + } + const resp = await client('search', params); return { span_types: resp.aggregations.types.buckets.map(bucket => ({ diff --git a/x-pack/plugins/apm/server/routes/errors.js b/x-pack/plugins/apm/server/routes/errors.js index 47b28db6e5f4d6..70bc4fb78bb20a 100644 --- a/x-pack/plugins/apm/server/routes/errors.js +++ b/x-pack/plugins/apm/server/routes/errors.js @@ -11,7 +11,7 @@ import { getDistribution } from '../lib/errors/distribution/get_distribution'; import { getErrorGroups } from '../lib/errors/get_error_groups'; import { getErrorGroup } from '../lib/errors/get_error_group'; import { setupRequest } from '../lib/helpers/setup_request'; -import { dateValidation } from '../lib/helpers/date_validation'; +import { withDefaultValidators } from '../lib/helpers/input_validation'; const pre = [{ method: setupRequest, assign: 'setup' }]; const ROOT = '/api/apm/services/{serviceName}/errors'; @@ -27,9 +27,7 @@ export function initErrorsApi(server) { config: { pre, validate: { - query: Joi.object().keys({ - start: dateValidation, - end: dateValidation, + query: withDefaultValidators({ q: Joi.string().allow(''), sortBy: Joi.string(), sortOrder: Joi.string() @@ -59,10 +57,7 @@ export function initErrorsApi(server) { config: { pre, validate: { - query: Joi.object().keys({ - start: dateValidation, - end: dateValidation - }) + query: withDefaultValidators() } }, handler: (req, reply) => { @@ -80,10 +75,7 @@ export function initErrorsApi(server) { config: { pre, validate: { - query: Joi.object().keys({ - start: dateValidation, - end: dateValidation - }) + query: withDefaultValidators() } }, handler: (req, reply) => { diff --git a/x-pack/plugins/apm/server/routes/services.js b/x-pack/plugins/apm/server/routes/services.js index 6976fac87b143c..90a3d923800ba6 100644 --- a/x-pack/plugins/apm/server/routes/services.js +++ b/x-pack/plugins/apm/server/routes/services.js @@ -4,12 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import Joi from 'joi'; import Boom from 'boom'; import { getServices } from '../lib/services/get_services'; import { getService } from '../lib/services/get_service'; import { setupRequest } from '../lib/helpers/setup_request'; -import { dateValidation } from '../lib/helpers/date_validation'; +import { withDefaultValidators } from '../lib/helpers/input_validation'; const ROOT = '/api/apm/services'; const pre = [{ method: setupRequest, assign: 'setup' }]; @@ -25,10 +24,7 @@ export function initServicesApi(server) { config: { pre, validate: { - query: Joi.object().keys({ - start: dateValidation, - end: dateValidation - }) + query: withDefaultValidators() } }, handler: (req, reply) => { @@ -45,10 +41,7 @@ export function initServicesApi(server) { config: { pre, validate: { - query: Joi.object().keys({ - start: dateValidation, - end: dateValidation - }) + query: withDefaultValidators() } }, handler: (req, reply) => { diff --git a/x-pack/plugins/apm/server/routes/transactions.js b/x-pack/plugins/apm/server/routes/transactions.js index fab05eeca18041..1bad37fece9c27 100644 --- a/x-pack/plugins/apm/server/routes/transactions.js +++ b/x-pack/plugins/apm/server/routes/transactions.js @@ -14,7 +14,7 @@ import { getTransactionDuration } from '../lib/transactions/get_transaction_dura import { getTopTransactions } from '../lib/transactions/get_top_transactions'; import getTransaction from '../lib/transactions/get_transaction'; import { setupRequest } from '../lib/helpers/setup_request'; -import { dateValidation } from '../lib/helpers/date_validation'; +import { withDefaultValidators } from '../lib/helpers/input_validation'; const pre = [{ method: setupRequest, assign: 'setup' }]; const ROOT = '/api/apm/services/{serviceName}/transactions'; @@ -30,9 +30,7 @@ export function initTransactionsApi(server) { config: { pre, validate: { - query: Joi.object().keys({ - start: dateValidation, - end: dateValidation, + query: withDefaultValidators({ transaction_type: Joi.string().default('request'), query: Joi.string() }) @@ -59,10 +57,7 @@ export function initTransactionsApi(server) { config: { pre, validate: { - query: Joi.object().keys({ - start: dateValidation, - end: dateValidation - }) + query: withDefaultValidators() } }, handler: (req, reply) => { @@ -80,10 +75,7 @@ export function initTransactionsApi(server) { config: { pre, validate: { - query: Joi.object().keys({ - start: dateValidation, - end: dateValidation - }) + query: withDefaultValidators() } }, handler: (req, reply) => { @@ -104,9 +96,7 @@ export function initTransactionsApi(server) { config: { pre, validate: { - query: Joi.object().keys({ - start: dateValidation, - end: dateValidation, + query: withDefaultValidators({ transaction_type: Joi.string().default('request'), transaction_name: Joi.string(), query: Joi.string() @@ -136,9 +126,7 @@ export function initTransactionsApi(server) { config: { pre, validate: { - query: Joi.object().keys({ - start: dateValidation, - end: dateValidation, + query: withDefaultValidators({ transaction_name: Joi.string().required() }) } diff --git a/x-pack/plugins/console_extensions/index.js b/x-pack/plugins/console_extensions/index.js index 62e99274412716..0299b09d05adb5 100644 --- a/x-pack/plugins/console_extensions/index.js +++ b/x-pack/plugins/console_extensions/index.js @@ -9,6 +9,20 @@ export function consoleExtensions(kibana) { return new kibana.Plugin({ id: 'console_extensions', require: ['kibana', 'console'], + isEnabled(config) { + return ( + config.get('console_extensions.enabled') && + config.has('console.enabled') && + config.get('console.enabled') + ); + }, + + config(Joi) { + return Joi.object({ + enabled: Joi.boolean().default(true), + }).default(); + }, + init: server => { if ( server.plugins.console && diff --git a/x-pack/plugins/dashboard_mode/index.js b/x-pack/plugins/dashboard_mode/index.js index ba6124a5b79529..4333aa772c779b 100644 --- a/x-pack/plugins/dashboard_mode/index.js +++ b/x-pack/plugins/dashboard_mode/index.js @@ -27,8 +27,10 @@ export function dashboardMode(kibana) { uiExports: { uiSettingDefaults: { [CONFIG_DASHBOARD_ONLY_MODE_ROLES]: { - description: 'Roles that belong to View Dashboards Only mode', - value: ['kibana_dashboard_only_user'], + name: 'Dashboards only roles', + description: `Roles that belong to View Dashboards Only mode`, + value: ['kibana_dashboard_only_user', 'kibana_rbac_dashboard_only_user'], + category: ['dashboard'], } }, app: { @@ -38,18 +40,6 @@ export function dashboardMode(kibana) { hidden: true, description: 'view dashboards', main: 'plugins/dashboard_mode/dashboard_viewer', - uses: [ - 'visTypes', - 'visResponseHandlers', - 'visRequestHandlers', - 'visEditorTypes', - 'savedObjectTypes', - 'embeddableFactories', - 'spyModes', - 'navbarExtensions', - 'docViews', - 'fieldFormats' - ], links: [ { id: 'kibana:dashboard', diff --git a/x-pack/plugins/dashboard_mode/public/dashboard_viewer.js b/x-pack/plugins/dashboard_mode/public/dashboard_viewer.js index 485c1ad5af0bf0..13e5b9a4e99c0d 100644 --- a/x-pack/plugins/dashboard_mode/public/dashboard_viewer.js +++ b/x-pack/plugins/dashboard_mode/public/dashboard_viewer.js @@ -13,6 +13,18 @@ import chrome from 'ui/chrome'; import routes from 'ui/routes'; import { uiModules } from 'ui/modules'; +// import the uiExports that we want to "use" +import 'uiExports/visTypes'; +import 'uiExports/visResponseHandlers'; +import 'uiExports/visRequestHandlers'; +import 'uiExports/visEditorTypes'; +import 'uiExports/savedObjectTypes'; +import 'uiExports/embeddableFactories'; +import 'uiExports/spyModes'; +import 'uiExports/navbarExtensions'; +import 'uiExports/docViews'; +import 'uiExports/fieldFormats'; + import _ from 'lodash'; import 'ui/autoload/all'; import 'plugins/kibana/dashboard'; diff --git a/x-pack/plugins/graph/index.js b/x-pack/plugins/graph/index.js index ebb6d6fba92652..dfb4410e4ec7c7 100644 --- a/x-pack/plugins/graph/index.js +++ b/x-pack/plugins/graph/index.js @@ -23,10 +23,6 @@ export function graph(kibana) { icon: 'plugins/graph/icon.png', description: 'Graph exploration', main: 'plugins/graph/app', - uses: [ - 'fieldFormats', - 'savedObjectTypes', - ] }, hacks: ['plugins/graph/hacks/toggle_app_link_in_nav'], home: ['plugins/graph/register_feature'], diff --git a/x-pack/plugins/graph/public/app.js b/x-pack/plugins/graph/public/app.js index accd741dfabeb4..49b35816b326f4 100644 --- a/x-pack/plugins/graph/public/app.js +++ b/x-pack/plugins/graph/public/app.js @@ -8,6 +8,10 @@ import d3 from 'd3'; import 'ace'; import rison from 'rison-node'; +// import the uiExports that we want to "use" +import 'uiExports/fieldFormats'; +import 'uiExports/savedObjectTypes'; + import 'ui/autoload/all'; import 'ui/directives/saved_object_finder'; import chrome from 'ui/chrome'; diff --git a/x-pack/plugins/graph/public/assets/app_graph.svg b/x-pack/plugins/graph/public/assets/app_graph.svg deleted file mode 100644 index 489d7ffdd2650c..00000000000000 --- a/x-pack/plugins/graph/public/assets/app_graph.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/graph/public/register_feature.js b/x-pack/plugins/graph/public/register_feature.js index 342c19d450174b..d7806149725629 100644 --- a/x-pack/plugins/graph/public/register_feature.js +++ b/x-pack/plugins/graph/public/register_feature.js @@ -13,7 +13,7 @@ FeatureCatalogueRegistryProvider.register(() => { id: 'graph', title: 'Graph', description: 'Surface and analyze relevant relationships in your Elasticsearch data.', - icon: '/plugins/graph/assets/app_graph.svg', + icon: 'graphApp', path: '/app/graph', showOnHomePage: true, category: FeatureCatalogueCategory.DATA diff --git a/x-pack/plugins/grokdebugger/common/constants/editor.js b/x-pack/plugins/grokdebugger/common/constants/editor.js new file mode 100644 index 00000000000000..a9c74ee18e4212 --- /dev/null +++ b/x-pack/plugins/grokdebugger/common/constants/editor.js @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const EDITOR = { + PATTERN_MIN_LINES: 3, + PATTERN_MAX_LINES: 10, + SAMPLE_DATA_MIN_LINES: 3, + SAMPLE_DATA_MAX_LINES: 50, + SCROLL_MARGIN_TOP_PX: 4, + SCROLL_MARGIN_BOTTOM_PX: 4, +}; diff --git a/x-pack/plugins/grokdebugger/common/constants/index.js b/x-pack/plugins/grokdebugger/common/constants/index.js index 85b819624b70fd..12e440d7ed8582 100644 --- a/x-pack/plugins/grokdebugger/common/constants/index.js +++ b/x-pack/plugins/grokdebugger/common/constants/index.js @@ -6,3 +6,4 @@ export { ROUTES } from './routes'; export { PLUGIN } from './plugin'; +export { EDITOR } from './editor'; diff --git a/x-pack/plugins/grokdebugger/public/assets/app_grok.svg b/x-pack/plugins/grokdebugger/public/assets/app_grok.svg deleted file mode 100644 index a83e635d4abe68..00000000000000 --- a/x-pack/plugins/grokdebugger/public/assets/app_grok.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/x-pack/plugins/grokdebugger/public/lib/ace/apply_editor_options.js b/x-pack/plugins/grokdebugger/public/lib/ace/apply_editor_options.js new file mode 100644 index 00000000000000..fb178711b77ee6 --- /dev/null +++ b/x-pack/plugins/grokdebugger/public/lib/ace/apply_editor_options.js @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EDITOR } from '../../../common/constants'; + +export function applyEditorOptions(editor, minLines, maxLines) { + editor.getSession().setUseWrapMode(true); + + /* + * This sets the space between the editor's borders and the + * edges of the top/bottom lines to make for a less-crowded + * typing experience. + */ + editor.renderer.setScrollMargin( + EDITOR.SCROLL_MARGIN_TOP_PX, + EDITOR.SCROLL_MARGIN_BOTTOM_PX, + 0, + 0 + ); + + editor.setOptions({ + highlightActiveLine: false, + highlightGutterLine: false, + minLines, + maxLines + }); + + editor.$blockScrolling = Infinity; +} diff --git a/x-pack/plugins/grokdebugger/public/lib/ace/apply_editor_options.test.js b/x-pack/plugins/grokdebugger/public/lib/ace/apply_editor_options.test.js new file mode 100644 index 00000000000000..79724369a20a22 --- /dev/null +++ b/x-pack/plugins/grokdebugger/public/lib/ace/apply_editor_options.test.js @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { applyEditorOptions } from './apply_editor_options'; +import { EDITOR } from '../../../common/constants'; + +describe('applyEditorOptions', () => { + let editor; + let setUseWrapMode; + let setScrollMargin; + let setOptions; + + beforeEach(() => { + setUseWrapMode = jest.fn(); + setScrollMargin = jest.fn(); + setOptions = jest.fn(); + + editor = { + getSession: () => { + return { setUseWrapMode }; + }, + renderer: { + setScrollMargin, + }, + setOptions, + }; + }); + + it('creates default props and given line sizes', () => { + const minLines = 14; + const maxLines = 90; + + applyEditorOptions(editor, minLines, maxLines); + + expect(setUseWrapMode.mock.calls).toHaveLength(1); + expect(setUseWrapMode.mock.calls[0][0]).toBe(true); + + expect(setScrollMargin.mock.calls).toHaveLength(1); + expect(setScrollMargin.mock.calls[0][0]).toEqual(EDITOR.SCROLL_MARGIN_TOP_PX); + expect(setScrollMargin.mock.calls[0][1]).toEqual(EDITOR.SCROLL_MARGIN_BOTTOM_PX); + expect(setScrollMargin.mock.calls[0][2]).toEqual(0); + expect(setScrollMargin.mock.calls[0][3]).toEqual(0); + + expect(setOptions.mock.calls).toHaveLength(1); + expect(setOptions.mock.calls[0][0]).toEqual({ + highlightActiveLine: false, + highlightGutterLine: false, + minLines: 14, + maxLines: 90, + }); + + expect(editor.$blockScrolling).toEqual(Infinity); + }); +}); diff --git a/x-pack/plugins/grokdebugger/public/lib/ace/grok_highlight_rules.js b/x-pack/plugins/grokdebugger/public/lib/ace/grok_highlight_rules.js new file mode 100644 index 00000000000000..74bd67c0ca80ca --- /dev/null +++ b/x-pack/plugins/grokdebugger/public/lib/ace/grok_highlight_rules.js @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import ace from 'ace'; + +const { TextHighlightRules } = ace.acequire('ace/mode/text_highlight_rules'); + +export class GrokHighlightRules extends TextHighlightRules { + constructor() { + super(); + this.$rules = { + start: [ + { + token: [ + "grokStart", + "grokPatternName", + "grokSeparator", + "grokFieldName", + "grokEnd" + ], + regex: "(%{)([^:]+)(:)([^:]+)(})" + }, + { + token: [ + "grokStart", + "grokPatternName", + "grokSeparator", + "grokFieldName", + "grokSeparator", + "grokFieldType", + "grokEnd" + ], + regex: "(%{)([^:]+)(:)([^:]+)(:)([^:]+)(})" + }, + { + token: (escapeToken, /* regexToken */) => { + if (escapeToken) { + return [ 'grokEscape', 'grokEscaped' ]; + } + return 'grokRegex'; + }, + regex: "(\\\\)?([\\[\\]\\(\\)\\?\\:\\|])" + }, + ] + }; + } +} diff --git a/x-pack/plugins/grokdebugger/public/lib/ace/grok_mode.js b/x-pack/plugins/grokdebugger/public/lib/ace/grok_mode.js new file mode 100644 index 00000000000000..5c3fe93d02a855 --- /dev/null +++ b/x-pack/plugins/grokdebugger/public/lib/ace/grok_mode.js @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import ace from 'ace'; +import { GrokHighlightRules } from './grok_highlight_rules'; + +const TextMode = ace.acequire("ace/mode/text").Mode; + +export class GrokMode extends TextMode { + constructor() { + super(); + this.HighlightRules = GrokHighlightRules; + } +} diff --git a/x-pack/plugins/grokdebugger/public/lib/ace/index.js b/x-pack/plugins/grokdebugger/public/lib/ace/index.js new file mode 100644 index 00000000000000..a34c891bd0d2cb --- /dev/null +++ b/x-pack/plugins/grokdebugger/public/lib/ace/index.js @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { GrokMode } from './grok_mode'; +export { applyEditorOptions } from './apply_editor_options'; diff --git a/x-pack/plugins/grokdebugger/public/register_feature.js b/x-pack/plugins/grokdebugger/public/register_feature.js index dbee5db15a1f7d..0dcca799136e7e 100644 --- a/x-pack/plugins/grokdebugger/public/register_feature.js +++ b/x-pack/plugins/grokdebugger/public/register_feature.js @@ -13,7 +13,7 @@ FeatureCatalogueRegistryProvider.register(() => { id: 'grokdebugger', title: 'Grok Debugger', description: 'Simulate and debug grok patterns for data transformation on ingestion.', - icon: '/plugins/grokdebugger/assets/app_grok.svg', + icon: 'grokApp', path: '/app/kibana#/dev_tools/grokdebugger', showOnHomePage: false, category: FeatureCatalogueCategory.ADMIN diff --git a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.html b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.html index 5c47a0b9c194ff..d252743e7a2672 100644 --- a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.html +++ b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.html @@ -22,15 +22,17 @@
-
+
+
diff --git a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.js b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.js index 243744bb7c1056..7f3b3099df7b0d 100644 --- a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.js +++ b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/custom_patterns_input/custom_patterns_input.js @@ -6,6 +6,8 @@ import { uiModules } from 'ui/modules'; import { InitAfterBindingsWorkaround } from 'ui/compat'; +import { EDITOR } from '../../../../../common/constants'; +import { applyEditorOptions } from '../../../../lib/ace'; import template from './custom_patterns_input.html'; import './custom_patterns_input.less'; import 'ui/toggle_panel'; @@ -32,14 +34,7 @@ app.directive('customPatternsInput', function () { }); $scope.aceLoaded = (editor) => { this.editor = editor; - editor.getSession().setUseWrapMode(true); - editor.setOptions({ - highlightActiveLine: false, - highlightGutterLine: false, - minLines: 3, - maxLines: 25 - }); - editor.$blockScrolling = Infinity; + applyEditorOptions(editor, EDITOR.PATTERN_MIN_LINES, EDITOR.PATTERN_MAX_LINES); }; } diff --git a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.html b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.html index 364e9df0ef770f..ab4f97223a03f4 100644 --- a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.html +++ b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.html @@ -3,14 +3,16 @@ -
+
+
+
diff --git a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.js b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.js index 870c0353945d4c..24a1fdcbebd5a8 100644 --- a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.js +++ b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/event_input/event_input.js @@ -5,6 +5,8 @@ */ import { uiModules } from 'ui/modules'; +import { EDITOR } from '../../../../../common/constants'; +import { applyEditorOptions } from '../../../../lib/ace'; import template from './event_input.html'; import './event_input.less'; import 'ace'; @@ -27,14 +29,7 @@ app.directive('eventInput', function () { }); $scope.aceLoaded = (editor) => { this.editor = editor; - editor.getSession().setUseWrapMode(true); - editor.setOptions({ - highlightActiveLine: false, - highlightGutterLine: false, - minLines: 3, - maxLines: 10 - }); - editor.$blockScrolling = Infinity; + applyEditorOptions(editor, EDITOR.SAMPLE_DATA_MIN_LINES, EDITOR.SAMPLE_DATA_MAX_LINES); }; } } diff --git a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/grokdebugger/grokdebugger.less b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/grokdebugger/grokdebugger.less index 9d7df2f2a3e6eb..ac2b1367e20ed0 100644 --- a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/grokdebugger/grokdebugger.less +++ b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/grokdebugger/grokdebugger.less @@ -18,4 +18,25 @@ grokdebugger { .grokdebugger-simulate-button { margin-bottom: 10px; } + + .ace_grokStart, + .ace_grokEnd, + .ace_grokSeparator, + .ace_grokEscape { + color: #999999; // euiColorMediumShade + } + + .ace_grokPatternName { + color: #017F75; // euiColorSecondary + } + + .ace_grokFieldName, + .ace_grokRegex { + color: #0079A5; // euiColorPrimary + } + + .ace_grokFieldType { + color: #0079A5; // euiColorPrimary + font-style: italic; + } } diff --git a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.html b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.html index 32f35386ad3208..4c6acc5d374b18 100644 --- a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.html +++ b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.html @@ -3,14 +3,16 @@ -
+
+
+
diff --git a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.js b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.js index 7fd4417fb2914d..d3119849dcedcb 100644 --- a/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.js +++ b/x-pack/plugins/grokdebugger/public/sections/grokdebugger/components/pattern_input/pattern_input.js @@ -5,8 +5,13 @@ */ import { uiModules } from 'ui/modules'; +import { EDITOR } from '../../../../../common/constants'; import template from './pattern_input.html'; import './pattern_input.less'; +import { + applyEditorOptions, + GrokMode +} from '../../../../lib/ace'; const app = uiModules.get('xpack/grokdebugger'); @@ -26,14 +31,8 @@ app.directive('patternInput', function () { }); $scope.aceLoaded = (editor) => { this.editor = editor; - editor.getSession().setUseWrapMode(true); - editor.setOptions({ - highlightActiveLine: false, - highlightGutterLine: false, - minLines: 3, - maxLines: 10 - }); - editor.$blockScrolling = Infinity; + applyEditorOptions(editor, EDITOR.PATTERN_MIN_LINES, EDITOR.PATTERN_MAX_LINES); + editor.getSession().setMode(new GrokMode()); }; } } diff --git a/x-pack/plugins/index_management/__jest__/components/index_table.test.js b/x-pack/plugins/index_management/__jest__/components/index_table.test.js index 7e43f2875870a7..4c8b7380e69cd3 100644 --- a/x-pack/plugins/index_management/__jest__/components/index_table.test.js +++ b/x-pack/plugins/index_management/__jest__/components/index_table.test.js @@ -32,6 +32,7 @@ jest.mock('react-ace', () => { } }; }); +jest.mock('brace/theme/textmate', () => 'brace/theme/textmate'); setHttpClient(axios.create()); let server = null; diff --git a/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/show_json/show_json.js b/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/show_json/show_json.js index 855b84eaafbb92..366107a7954724 100644 --- a/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/show_json/show_json.js +++ b/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/show_json/show_json.js @@ -7,6 +7,8 @@ import React from "react"; import { EuiCodeEditor } from "@elastic/eui"; +import 'brace/theme/textmate'; + export class ShowJson extends React.PureComponent { componentWillMount() { this.props.loadIndexData(this.props); @@ -26,10 +28,13 @@ export class ShowJson extends React.PureComponent { return ( ); } diff --git a/x-pack/plugins/index_management/server/lib/register_license_checker/register_license_checker.js b/x-pack/plugins/index_management/server/lib/register_license_checker/register_license_checker.js index 26b0091ef21905..8b826c01ea32f8 100644 --- a/x-pack/plugins/index_management/server/lib/register_license_checker/register_license_checker.js +++ b/x-pack/plugins/index_management/server/lib/register_license_checker/register_license_checker.js @@ -10,12 +10,12 @@ import { PLUGIN } from '../../../common/constants'; export function registerLicenseChecker(server) { const xpackMainPlugin = server.plugins.xpack_main; - const watcherPlugin = server.plugins.watcher; + const indexManagementPlugin = server.plugins.index_management; - mirrorPluginStatus(xpackMainPlugin, watcherPlugin); + mirrorPluginStatus(xpackMainPlugin, indexManagementPlugin); xpackMainPlugin.status.once('green', () => { // Register a function that is called whenever the xpack info changes, // to re-compute the license check results for this plugin xpackMainPlugin.info.feature(PLUGIN.ID).registerLicenseCheckResultsGenerator(checkLicense); }); -} \ No newline at end of file +} diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap index 31e0ee78e1456f..8596cc1b3208e4 100644 --- a/x-pack/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap +++ b/x-pack/plugins/license_management/__jest__/__snapshots__/add_license.test.js.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`AddLicense component when license is active should display correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

Update license
"`; +exports[`AddLicense component when license is active should display correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

Update license
"`; -exports[`AddLicense component when license is expired should display with correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

Update license
"`; +exports[`AddLicense component when license is expired should display with correct verbiage 1`] = `"
Update your license

If you already have a new license, upload it now.

Update license
"`; diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap index d8782624a7e7e8..7092dd34eb115b 100644 --- a/x-pack/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap +++ b/x-pack/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`LicenseStatus component should display display warning is expired 1`] = `"

Your platinum license has expired

Your license expired on
"`; +exports[`LicenseStatus component should display display warning is expired 1`] = `"

Your Platinum license has expired

Your license expired on
"`; -exports[`LicenseStatus component should display normally when license is active 1`] = `"

Your gold license is active

Your license will expire on October 12, 2099 7:00 PM EST
"`; +exports[`LicenseStatus component should display normally when license is active 1`] = `"

Your Gold license is active

Your license will expire on October 12, 2099 7:00 PM EST
"`; diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap index 6727f91105359d..96272104264ea6 100644 --- a/x-pack/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap +++ b/x-pack/plugins/license_management/__jest__/__snapshots__/request_trial_extension.test.js.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`RequestTrialExtension component should display when trial license is about to expire 1`] = `"
Extend your trial

If you’d like to continuing using Security, Machine Learning, and our other awesome platinum features, request an extension now.

Extend trial
"`; +exports[`RequestTrialExtension component should display when trial license is about to expire 1`] = `"
Extend your trial

If you’d like to continuing using Security, Machine Learning, and our other awesome platinum features, request an extension now.

Extend trial
"`; -exports[`RequestTrialExtension component should display when trial license is expired 1`] = `"
Extend your trial

If you’d like to continuing using Security, Machine Learning, and our other awesome platinum features, request an extension now.

Extend trial
"`; +exports[`RequestTrialExtension component should display when trial license is expired 1`] = `"
Extend your trial

If you’d like to continuing using Security, Machine Learning, and our other awesome platinum features, request an extension now.

Extend trial
"`; diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap index dc1ffa80099e60..83c79535b9961a 100644 --- a/x-pack/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap +++ b/x-pack/plugins/license_management/__jest__/__snapshots__/revert_to_basic.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`RevertToBasic component should display when license is about to expire 1`] = `"
Revert to basic license

You’ll revert to our free features and lose access to Security, Machine Learning and other platinum features.

"`; +exports[`RevertToBasic component should display when license is about to expire 1`] = `"
Revert to Basic license

You’ll revert to our free features and lose access to security, machine learning and other Platinum features.

"`; -exports[`RevertToBasic component should display when license is expired 1`] = `"
Revert to basic license

You’ll revert to our free features and lose access to Security, Machine Learning and other platinum features.

"`; +exports[`RevertToBasic component should display when license is expired 1`] = `"
Revert to Basic license

You’ll revert to our free features and lose access to security, machine learning and other Platinum features.

"`; -exports[`RevertToBasic component should display when trial is active 1`] = `"
Revert to basic license

You’ll revert to our free features and lose access to Security, Machine Learning and other platinum features.

"`; +exports[`RevertToBasic component should display when trial is active 1`] = `"
Revert to Basic license

You’ll revert to our free features and lose access to security, machine learning and other Platinum features.

"`; diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap index 170c23b35c2fe2..91ba9620637ef8 100644 --- a/x-pack/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap +++ b/x-pack/plugins/license_management/__jest__/__snapshots__/start_trial.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`StartTrial component when trial is allowed display for basic license 1`] = `"
Start a 30-day trial

Experience what Security, Machine Learning, and all our other platinum features have to offer.

"`; +exports[`StartTrial component when trial is allowed display for basic license 1`] = `"
Start a 30-day trial

Experience what security, machine learning, and all our other Platinum features have to offer.

"`; -exports[`StartTrial component when trial is allowed should display for expired platinum license 1`] = `"
Start a 30-day trial

Experience what Security, Machine Learning, and all our other platinum features have to offer.

"`; +exports[`StartTrial component when trial is allowed should display for expired platinum license 1`] = `"
Start a 30-day trial

Experience what security, machine learning, and all our other Platinum features have to offer.

"`; -exports[`StartTrial component when trial is allowed should display for gold license 1`] = `"
Start a 30-day trial

Experience what Security, Machine Learning, and all our other platinum features have to offer.

"`; +exports[`StartTrial component when trial is allowed should display for gold license 1`] = `"
Start a 30-day trial

Experience what security, machine learning, and all our other Platinum features have to offer.

"`; diff --git a/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap b/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap index 40624fe540c358..756f1215aa4d6b 100644 --- a/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap +++ b/x-pack/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap @@ -39,13 +39,14 @@ exports[`UploadLicense should display a modal when license requires acknowledgem
- +
@@ -208,7 +212,9 @@ exports[`UploadLicense should display a modal when license requires acknowledgem BASIC license. Review the list of features below.
- +
@@ -287,14 +293,18 @@ exports[`UploadLicense should display a modal when license requires acknowledgem - +
Your license key is a JSON file with a signature attached.
- +
@@ -318,11 +328,14 @@ exports[`UploadLicense should display a modal when license requires acknowledgem
- +
- +
Your license key is a JSON file with a signature attached.
- +
@@ -611,6 +630,7 @@ exports[`UploadLicense should display an error when ES says license is expired 1
- +
- +
Your license key is a JSON file with a signature attached.
- +
@@ -921,6 +950,7 @@ exports[`UploadLicense should display an error when ES says license is invalid 1
- +
- +
Your license key is a JSON file with a signature attached.
- +
@@ -1231,6 +1270,7 @@ exports[`UploadLicense should display an error when submitting invalid JSON 1`]
- +
- +
Your license key is a JSON file with a signature attached.
- +
@@ -1541,6 +1590,7 @@ exports[`UploadLicense should display error when ES returns error 1`] = `
- +
{ const { isActive, type } = getLicense(state); + const typeTitleCase = type.charAt(0).toUpperCase() + type.substr(1).toLowerCase(); return { status: isActive ? 'Active' : 'Inactive', - type, + type: typeTitleCase, isExpired: isExpired(state), expiryDate: getExpirationDateFormatted(state) }; diff --git a/x-pack/plugins/license_management/public/sections/license_dashboard/revert_to_basic/revert_to_basic.container.js b/x-pack/plugins/license_management/public/sections/license_dashboard/revert_to_basic/revert_to_basic.container.js index 083cb8c771393c..bd7f7c28be26f9 100644 --- a/x-pack/plugins/license_management/public/sections/license_dashboard/revert_to_basic/revert_to_basic.container.js +++ b/x-pack/plugins/license_management/public/sections/license_dashboard/revert_to_basic/revert_to_basic.container.js @@ -13,7 +13,7 @@ import { shouldShowRevertToBasicLicense, getStartBasicMessages } from '../../../store/reducers/licenseManagement'; -import { startBasicLicense } from '../../../store/actions/start_basic'; +import { startBasicLicense, cancelStartBasicLicense } from '../../../store/actions/start_basic'; const mapStateToProps = state => { return { @@ -25,7 +25,8 @@ const mapStateToProps = state => { }; const mapDispatchToProps = { - startBasicLicense + startBasicLicense, + cancelStartBasicLicense }; export const RevertToBasic = connect(mapStateToProps, mapDispatchToProps)( diff --git a/x-pack/plugins/license_management/public/sections/license_dashboard/revert_to_basic/revert_to_basic.js b/x-pack/plugins/license_management/public/sections/license_dashboard/revert_to_basic/revert_to_basic.js index 1131bf2239347d..47116689f1f31b 100644 --- a/x-pack/plugins/license_management/public/sections/license_dashboard/revert_to_basic/revert_to_basic.js +++ b/x-pack/plugins/license_management/public/sections/license_dashboard/revert_to_basic/revert_to_basic.js @@ -26,6 +26,7 @@ export class RevertToBasic extends React.PureComponent { needsAcknowledgement, messages: [firstLine, ...messages] = [], startBasicLicense, + cancelStartBasicLicense, licenseType } = this.props; if (!needsAcknowledgement) { @@ -35,8 +36,8 @@ export class RevertToBasic extends React.PureComponent { startBasicLicense(licenseType, HTMLMarqueeElement)} + onCancel={cancelStartBasicLicense} + onConfirm={() => startBasicLicense(licenseType, true)} cancelButtonText="Cancel" confirmButtonText="Confirm" > @@ -63,13 +64,13 @@ export class RevertToBasic extends React.PureComponent { } const description = ( - You’ll revert to our free features and lose access to Security, Machine - Learning and other{' '} + You’ll revert to our free features and lose access to security, machine + learning and other{' '} - platinum features + Platinum features . ); @@ -78,11 +79,11 @@ export class RevertToBasic extends React.PureComponent { {this.acknowledgeModal()} startBasicLicense(licenseType)}> - Revert to basic + Revert to Basic } /> diff --git a/x-pack/plugins/license_management/public/sections/license_dashboard/start_trial/start_trial.js b/x-pack/plugins/license_management/public/sections/license_dashboard/start_trial/start_trial.js index c150762e88bd01..32f12c343611e5 100644 --- a/x-pack/plugins/license_management/public/sections/license_dashboard/start_trial/start_trial.js +++ b/x-pack/plugins/license_management/public/sections/license_dashboard/start_trial/start_trial.js @@ -49,22 +49,22 @@ export class StartTrial extends React.PureComponent {

- This trial is for the full set of Elastic{' '} + This trial is for the full set of{' '} - platinum features - . You'll get immediate access to: + Platinum features + of the Elastic Stack. You'll get immediate access to:

  • Machine learning
  • Alerting
  • -
  • Graph
  • +
  • Graph capabilities
  • JDBC connectivity for SQL

- Security features, such authentication (native, AD/LDAP, SAML, + Security features, such as authentication (native, AD/LDAP, SAML, PKI), role-based access control, and auditing, require configuration. See the{' '} - Experience what Security, Machine Learning, and all our other{' '} + Experience what security, machine learning, and all our other{' '} - platinum features + Platinum features {' '} have to offer. diff --git a/x-pack/plugins/license_management/public/store/actions/start_basic.js b/x-pack/plugins/license_management/public/store/actions/start_basic.js index f2a652c173d3eb..831e5993de5e61 100644 --- a/x-pack/plugins/license_management/public/store/actions/start_basic.js +++ b/x-pack/plugins/license_management/public/store/actions/start_basic.js @@ -12,6 +12,10 @@ export const startBasicLicenseStatus = createAction( 'LICENSE_MANAGEMENT_START_BASIC_LICENSE_STATUS' ); +export const cancelStartBasicLicense = createAction( + 'LICENSE_MANAGEMENT_CANCEL_START_BASIC_LICENSE' +); + export const startBasicLicense = (currentLicenseType, ack) => async ( dispatch, getState, diff --git a/x-pack/plugins/license_management/public/store/reducers/start_basic_license_status.js b/x-pack/plugins/license_management/public/store/reducers/start_basic_license_status.js index cb558ce24a1161..19811ba10e70fd 100644 --- a/x-pack/plugins/license_management/public/store/reducers/start_basic_license_status.js +++ b/x-pack/plugins/license_management/public/store/reducers/start_basic_license_status.js @@ -6,11 +6,14 @@ import { handleActions } from 'redux-actions'; -import { startBasicLicenseStatus } from '../actions/start_basic'; +import { startBasicLicenseStatus, cancelStartBasicLicense } from '../actions/start_basic'; export const startBasicStatus = handleActions({ [startBasicLicenseStatus](state, { payload }) { return payload; + }, + [cancelStartBasicLicense]() { + return {}; } }, {}); diff --git a/x-pack/plugins/license_management/server/lib/start_trial.js b/x-pack/plugins/license_management/server/lib/start_trial.js index f2318a9e8867cb..3f80cb526b9924 100644 --- a/x-pack/plugins/license_management/server/lib/start_trial.js +++ b/x-pack/plugins/license_management/server/lib/start_trial.js @@ -22,7 +22,7 @@ export async function startTrial(req, xpackInfo) { const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('admin'); const options = { method: 'POST', - path: '_xpack/license/start_trial' + path: '_xpack/license/start_trial?acknowledge=true' }; try { /*eslint camelcase: 0*/ diff --git a/x-pack/plugins/logstash/common/constants/editor.js b/x-pack/plugins/logstash/common/constants/editor.js new file mode 100644 index 00000000000000..5da0cc2bc156a4 --- /dev/null +++ b/x-pack/plugins/logstash/common/constants/editor.js @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const EDITOR = { + /* + * The space between the top of the editor's first-line characters + * and the top border of the editor. + */ + PIPELINE_EDITOR_SCROLL_MARGIN_TOP_PX: 4, + + /* + * The space between the bottom of the editor's last-line characters + * and the bottom border of the editor. + */ + PIPELINE_EDITOR_SCROLL_MARGIN_BOTTOM_PX: 12, +}; diff --git a/x-pack/plugins/logstash/common/constants/index.js b/x-pack/plugins/logstash/common/constants/index.js index d6b83e58541260..c016e505045ee8 100644 --- a/x-pack/plugins/logstash/common/constants/index.js +++ b/x-pack/plugins/logstash/common/constants/index.js @@ -12,3 +12,5 @@ export { PLUGIN } from './plugin'; export { ES_SCROLL_SETTINGS } from './es_scroll_settings'; export { TOOLTIPS } from './tooltips'; export { PIPELINE } from './pipeline'; +export { MONITORING } from './monitoring'; +export { EDITOR } from './editor'; diff --git a/x-pack/plugins/logstash/common/constants/monitoring.js b/x-pack/plugins/logstash/common/constants/monitoring.js new file mode 100644 index 00000000000000..182507f3e04626 --- /dev/null +++ b/x-pack/plugins/logstash/common/constants/monitoring.js @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const MONITORING = { + + /** + * How far back in time (from now) do we look in Monitoring data for pipelines to be considered as "currently" running. This is + * also, deliberately, the same duration we give Monitoring to pick up and report on a recently-deleted pipeline before we + * are safe to stop tracking that pipeline as recently-deleted. + */ + ACTIVE_PIPELINE_RANGE_S: 30 +}; diff --git a/x-pack/plugins/logstash/public/assets/app_pipeline.svg b/x-pack/plugins/logstash/public/assets/app_pipeline.svg deleted file mode 100644 index fde22d1d2343ac..00000000000000 --- a/x-pack/plugins/logstash/public/assets/app_pipeline.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/x-pack/plugins/logstash/public/lib/register_home_feature/register_home_feature.js b/x-pack/plugins/logstash/public/lib/register_home_feature/register_home_feature.js index 7becde2ab702a1..106008dc4190e5 100644 --- a/x-pack/plugins/logstash/public/lib/register_home_feature/register_home_feature.js +++ b/x-pack/plugins/logstash/public/lib/register_home_feature/register_home_feature.js @@ -17,7 +17,7 @@ FeatureCatalogueRegistryProvider.register(($injector) => { id: 'management_logstash', title: 'Logstash Pipelines', description: 'Create, delete, update, and clone data ingestion pipelines.', - icon: '/plugins/logstash/assets/app_pipeline.svg', + icon: 'pipelineApp', path: '/app/kibana#/management/logstash/pipelines', showOnHomePage: true, category: FeatureCatalogueCategory.ADMIN diff --git a/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.html b/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.html index 8394145859ad33..07e133fe17550a 100644 --- a/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.html +++ b/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.html @@ -98,16 +98,17 @@ > Pipeline -

+
+
+
diff --git a/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.js b/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.js index 9904486c48412e..0ba44bf6a53d1e 100644 --- a/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.js +++ b/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.js @@ -14,7 +14,7 @@ import 'plugins/logstash/services/license'; import 'plugins/logstash/services/security'; import './pipeline_edit.less'; import '../../../../components/tooltip'; -import { TOOLTIPS } from '../../../../../common/constants'; +import { EDITOR, TOOLTIPS } from '../../../../../common/constants'; import 'ace'; const app = uiModules.get('xpack/logstash'); @@ -31,7 +31,7 @@ app.directive('pipelineEdit', function ($injector) { restrict: 'E', template: template, scope: { - pipeline: '=' + pipeline: '=', }, bindToController: true, controllerAs: 'pipelineEdit', @@ -46,13 +46,23 @@ app.directive('pipelineEdit', function ($injector) { } else { $scope.user = null; } - $scope.aceLoaded = (editor) => { + $scope.aceLoaded = editor => { this.editor = editor; + /* + * This sets the space between the editor's borders and the + * edges of the top/bottom lines to make for a less-crowded + * typing experience. + */ + editor.renderer.setScrollMargin( + EDITOR.PIPELINE_EDITOR_SCROLL_MARGIN_TOP_PX, + EDITOR.PIPELINE_EDITOR_SCROLL_MARGIN_BOTTOM_PX, + 0, + 0 + ); editor.setReadOnly(this.isReadOnly); - editor.getSession().setMode("ace/mode/ruby"); editor.setOptions({ minLines: 25, - maxLines: Infinity + maxLines: Infinity, }); editor.$blockScrolling = Infinity; }; @@ -62,52 +72,61 @@ app.directive('pipelineEdit', function ($injector) { this.tooltips = TOOLTIPS; - dirtyPrompt.register(() => !this.pipeline.isEqualTo(this.originalPipeline)); + dirtyPrompt.register( + () => !this.pipeline.isEqualTo(this.originalPipeline) + ); $scope.$on('$destroy', dirtyPrompt.deregister); } - onPipelineSave = (username) => { + onPipelineSave = username => { this.pipeline.username = username; - return pipelineService.savePipeline(this.pipeline) + return pipelineService + .savePipeline(this.pipeline) .then(() => { toastNotifications.addSuccess(`Saved '${this.pipeline.id}'`); this.close(); }) .catch(err => { - return licenseService.checkValidity() + return licenseService + .checkValidity() .then(() => this.notifier.error(err)); }); - } + }; - onPipelineDelete = (pipelineId) => { + onPipelineDelete = pipelineId => { const confirmModalOptions = { onConfirm: this.deletePipeline, - confirmButtonText: `Delete pipeline ${pipelineId}` + confirmButtonText: `Delete pipeline ${pipelineId}`, }; - return confirmModal('You cannot recover a deleted pipeline.', confirmModalOptions); - } + return confirmModal( + 'You cannot recover a deleted pipeline.', + confirmModalOptions + ); + }; onClose = () => { this.close(); - } + }; deletePipeline = () => { - return pipelineService.deletePipeline(this.pipeline.id) + return pipelineService + .deletePipeline(this.pipeline.id) .then(() => { toastNotifications.addSuccess(`Deleted '${this.pipeline.id}'`); this.close(); }) .catch(err => { - return licenseService.checkValidity() + return licenseService + .checkValidity() .then(() => this.notifier.error(err)); }); - } + }; close = () => { dirtyPrompt.deregister(); kbnUrl.change('/management/logstash/pipelines', {}); - } + }; get isSaveEnabled() { return !(this.form.$invalid || this.jsonForm.$invalid); @@ -116,6 +135,6 @@ app.directive('pipelineEdit', function ($injector) { get isReadOnly() { return licenseService.isReadOnly; } - } + }, }; }); diff --git a/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.less b/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.less index 56e13a125e9b69..f5c00fc6a495fe 100644 --- a/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.less +++ b/x-pack/plugins/logstash/public/sections/pipeline_edit/components/pipeline_edit/pipeline_edit.less @@ -4,7 +4,6 @@ pipeline-edit { .pipeline-editor { - height:400px; border: 1px solid #ecf0f1; } } diff --git a/x-pack/plugins/logstash/public/services/monitoring/monitoring_service.js b/x-pack/plugins/logstash/public/services/monitoring/monitoring_service.js index 3d993cb4f2c462..a160408bcaa023 100644 --- a/x-pack/plugins/logstash/public/services/monitoring/monitoring_service.js +++ b/x-pack/plugins/logstash/public/services/monitoring/monitoring_service.js @@ -6,7 +6,10 @@ import moment from 'moment'; import chrome from 'ui/chrome'; -import { ROUTES } from '../../../common/constants'; +import { + ROUTES, + MONITORING +} from '../../../common/constants'; import { PipelineListItem } from 'plugins/logstash/models/pipeline_list_item'; export class MonitoringService { @@ -34,7 +37,7 @@ export class MonitoringService { const body = { timeRange: { max: now.toISOString(), - min: now.subtract(30, 'seconds').toISOString() + min: now.subtract(MONITORING.ACTIVE_PIPELINE_RANGE_S, 'seconds').toISOString() } }; return this.$http.post(url, body); diff --git a/x-pack/plugins/logstash/public/services/pipeline/pipeline_service.factory.js b/x-pack/plugins/logstash/public/services/pipeline/pipeline_service.factory.js index ac939956afcedd..a276d22f53c889 100644 --- a/x-pack/plugins/logstash/public/services/pipeline/pipeline_service.factory.js +++ b/x-pack/plugins/logstash/public/services/pipeline/pipeline_service.factory.js @@ -10,5 +10,6 @@ import { PipelineService } from './pipeline_service'; uiModules.get('xpack/logstash') .factory('pipelineService', ($injector) => { const $http = $injector.get('$http'); - return new PipelineService($http); + const pipelinesService = $injector.get('pipelinesService'); + return new PipelineService($http, pipelinesService); }); diff --git a/x-pack/plugins/logstash/public/services/pipeline/pipeline_service.js b/x-pack/plugins/logstash/public/services/pipeline/pipeline_service.js index c027a3e97f6f97..2a299e3fac8408 100644 --- a/x-pack/plugins/logstash/public/services/pipeline/pipeline_service.js +++ b/x-pack/plugins/logstash/public/services/pipeline/pipeline_service.js @@ -9,8 +9,9 @@ import { ROUTES } from '../../../common/constants'; import { Pipeline } from 'plugins/logstash/models/pipeline'; export class PipelineService { - constructor($http) { + constructor($http, pipelinesService) { this.$http = $http; + this.pipelinesService = pipelinesService; this.basePath = chrome.addBasePath(ROUTES.API_ROOT); } @@ -30,6 +31,7 @@ export class PipelineService { deletePipeline(id) { return this.$http.delete(`${this.basePath}/pipeline/${id}`) + .then(() => this.pipelinesService.addToRecentlyDeleted(id)) .catch(e => { throw e.data.message; }); diff --git a/x-pack/plugins/logstash/public/services/pipelines/pipelines_service.factory.js b/x-pack/plugins/logstash/public/services/pipelines/pipelines_service.factory.js index 0685335e9402ed..7ff42cae7d9997 100644 --- a/x-pack/plugins/logstash/public/services/pipelines/pipelines_service.factory.js +++ b/x-pack/plugins/logstash/public/services/pipelines/pipelines_service.factory.js @@ -11,7 +11,8 @@ import '../monitoring'; uiModules.get('xpack/logstash') .factory('pipelinesService', ($injector) => { const $http = $injector.get('$http'); + const $window = $injector.get('$window'); const Promise = $injector.get('Promise'); const monitoringService = $injector.get('xpackLogstashMonitoringService'); - return new PipelinesService($http, Promise, monitoringService); + return new PipelinesService($http, $window, Promise, monitoringService); }); diff --git a/x-pack/plugins/logstash/public/services/pipelines/pipelines_service.js b/x-pack/plugins/logstash/public/services/pipelines/pipelines_service.js index 04b612f7344d19..4cdd791b678d24 100644 --- a/x-pack/plugins/logstash/public/services/pipelines/pipelines_service.js +++ b/x-pack/plugins/logstash/public/services/pipelines/pipelines_service.js @@ -5,12 +5,18 @@ */ import chrome from 'ui/chrome'; -import { ROUTES } from '../../../common/constants'; +import { + ROUTES, + MONITORING +} from '../../../common/constants'; import { PipelineListItem } from 'plugins/logstash/models/pipeline_list_item'; +const RECENTLY_DELETED_PIPELINE_IDS_STORAGE_KEY = 'xpack.logstash.recentlyDeletedPipelines'; + export class PipelinesService { - constructor($http, Promise, monitoringService) { + constructor($http, $window, Promise, monitoringService) { this.$http = $http; + this.$window = $window; this.Promise = Promise; this.monitoringService = monitoringService; this.basePath = chrome.addBasePath(ROUTES.API_ROOT); @@ -22,11 +28,38 @@ export class PipelinesService { this.getMonitoringPipelineList() ]) .then(([managementPipelines, monitoringPipelines]) => { + const now = Date.now(); + + // Monitoring will report centrally-managed pipelines as well, including recently-deleted centrally-managed ones. + // If there's a recently-deleted pipeline we're keeping track of BUT monitoring doesn't report it, that means + // it's not running in Logstash any more. So we can stop tracking it as a recently-deleted pipeline. + const monitoringPipelineIds = monitoringPipelines.map(pipeline => pipeline.id); + this.getRecentlyDeleted().forEach(recentlyDeletedPipeline => { + // We don't want to stop tracking the recently-deleted pipeline until Monitoring has had some + // time to report on it. Otherwise, if we stop tracking first, *then* Monitoring reports it, we'll + // still end up showing it in the list until Monitoring stops reporting it. + if (now - recentlyDeletedPipeline.deletedOn < (MONITORING.ACTIVE_PIPELINE_RANGE_S * 1000)) { + return; + } + + // If Monitoring is still reporting the pipeline, don't stop tracking it yet + if (monitoringPipelineIds.includes(recentlyDeletedPipeline.id)) { + return; + } + + this.removeFromRecentlyDeleted(recentlyDeletedPipeline.id); + }); + // Merge centrally-managed pipelines with pipelines reported by monitoring. Take care to dedupe - // while merging because monitoring will (rightly) report centrally-managed pipelines as well! + // while merging because monitoring will (rightly) report centrally-managed pipelines as well, + // including recently-deleted ones! const managementPipelineIds = managementPipelines.map(pipeline => pipeline.id); return managementPipelines.concat( - monitoringPipelines.filter(monitoringPipeline => !managementPipelineIds.includes(monitoringPipeline.id)) + monitoringPipelines + .filter(monitoringPipeline => + !managementPipelineIds.includes(monitoringPipeline.id) + && !this.isRecentlyDeleted(monitoringPipeline.id) + ) ); }); } @@ -55,6 +88,48 @@ export class PipelinesService { headers: { 'Content-Type': 'application/json' } }; return this.$http.delete(`${this.basePath}/pipelines`, requestOpts) - .then(response => response.data.results); + .then(response => { + this.addToRecentlyDeleted(...pipelineIds); + return response.data.results; + }); + } + + addToRecentlyDeleted(...pipelineIds) { + const recentlyDeletedPipelines = this.getRecentlyDeleted(); + const recentlyDeletedPipelineIds = recentlyDeletedPipelines.map(pipeline => pipeline.id); + pipelineIds.forEach(pipelineId => { + if (!recentlyDeletedPipelineIds.includes(pipelineId)) { + recentlyDeletedPipelines.push({ + id: pipelineId, + deletedOn: Date.now() + }); + } + }); + this.setRecentlyDeleted(recentlyDeletedPipelines); + } + + removeFromRecentlyDeleted(...pipelineIds) { + const recentlyDeletedPipelinesToKeep = this.getRecentlyDeleted() + .filter(recentlyDeletedPipeline => !pipelineIds.includes(recentlyDeletedPipeline.id)); + this.setRecentlyDeleted(recentlyDeletedPipelinesToKeep); + } + + isRecentlyDeleted(pipelineId) { + return this.getRecentlyDeleted() + .map(pipeline => pipeline.id) + .includes(pipelineId); + } + + getRecentlyDeleted() { + const recentlyDeletedPipelines = this.$window.localStorage.getItem(RECENTLY_DELETED_PIPELINE_IDS_STORAGE_KEY); + if (!recentlyDeletedPipelines) { + return []; + } + + return JSON.parse(recentlyDeletedPipelines); + } + + setRecentlyDeleted(recentlyDeletedPipelineIds) { + this.$window.localStorage.setItem(RECENTLY_DELETED_PIPELINE_IDS_STORAGE_KEY, JSON.stringify(recentlyDeletedPipelineIds)); } } diff --git a/x-pack/plugins/ml/public/constants/index_patterns.js b/x-pack/plugins/ml/common/constants/index_patterns.js similarity index 100% rename from x-pack/plugins/ml/public/constants/index_patterns.js rename to x-pack/plugins/ml/common/constants/index_patterns.js diff --git a/x-pack/plugins/ml/public/util/__tests__/anomaly_utils.js b/x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js similarity index 99% rename from x-pack/plugins/ml/public/util/__tests__/anomaly_utils.js rename to x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js index 95631c1218c47b..0f47254bb90cc7 100644 --- a/x-pack/plugins/ml/public/util/__tests__/anomaly_utils.js +++ b/x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js @@ -265,6 +265,7 @@ describe('ML - anomaly utils', () => { it('returns true for expected function descriptions', () => { expect(showTypicalForFunction('count')).to.be(true); expect(showTypicalForFunction('distinct_count')).to.be(true); + expect(showTypicalForFunction('lat_long')).to.be(true); expect(showTypicalForFunction('mean')).to.be(true); expect(showTypicalForFunction('max')).to.be(true); expect(showTypicalForFunction('min')).to.be(true); @@ -276,7 +277,6 @@ describe('ML - anomaly utils', () => { }); it('returns false for expected function descriptions', () => { - expect(showTypicalForFunction('lat_long')).to.be(false); expect(showTypicalForFunction('rare')).to.be(false); }); diff --git a/x-pack/plugins/ml/common/util/__tests__/job_utils.js b/x-pack/plugins/ml/common/util/__tests__/job_utils.js index d535cd92bf970c..d9e03dfe1f6c63 100644 --- a/x-pack/plugins/ml/common/util/__tests__/job_utils.js +++ b/x-pack/plugins/ml/common/util/__tests__/job_utils.js @@ -113,7 +113,8 @@ describe('ML - job utils', () => { { 'function': 'sum', 'field_name': 'bytes', 'partition_field_name': 'clientip', 'detector_description': 'High bytes client IP' }, // eslint-disable-line max-len { 'function': 'freq_rare', 'by_field_name': 'uri', 'over_field_name': 'clientip', 'detector_description': 'Freq rare URI' }, { 'function': 'count', 'by_field_name': 'mlcategory', 'detector_description': 'Count by category' }, - { 'function': 'count', 'by_field_name': 'hrd', 'detector_description': 'count by hrd' } + { 'function': 'count', 'by_field_name': 'hrd', 'detector_description': 'count by hrd' }, + { 'function': 'mean', 'field_name': 'NetworkDiff', 'detector_description': 'avg NetworkDiff' } ] }, datafeed_config: { @@ -123,6 +124,12 @@ describe('ML - job utils', () => { 'inline': 'return domainSplit(doc["query"].value, params).get(1);', 'lang': 'painless' } + }, + 'NetworkDiff': { + 'script': { + 'source': 'doc["NetworkOut"].value - doc["NetworkIn"].value', + 'lang': 'painless' + } } } } @@ -140,10 +147,14 @@ describe('ML - job utils', () => { expect(isTimeSeriesViewDetector(job, 2)).to.be(false); }); - it('returns false for a detector using count on a scripted field', () => { + it('returns false for a detector using a script field as a by field', () => { expect(isTimeSeriesViewDetector(job, 3)).to.be(false); }); + it('returns false for a detector using a script field as a metric field_name', () => { + expect(isTimeSeriesViewDetector(job, 4)).to.be(false); + }); + }); describe('isTimeSeriesViewFunction', () => { diff --git a/x-pack/plugins/ml/public/util/anomaly_utils.js b/x-pack/plugins/ml/common/util/anomaly_utils.js similarity index 98% rename from x-pack/plugins/ml/public/util/anomaly_utils.js rename to x-pack/plugins/ml/common/util/anomaly_utils.js index e2f4f0c3f8be32..d367a061440fb2 100644 --- a/x-pack/plugins/ml/public/util/anomaly_utils.js +++ b/x-pack/plugins/ml/common/util/anomaly_utils.js @@ -18,7 +18,7 @@ const DISPLAY_ACTUAL_FUNCTIONS = ['count', 'distinct_count', 'lat_long', 'mean', 'median', 'varp', 'info_content', 'time']; // List of function descriptions for which typical values from record level results should be displayed. -const DISPLAY_TYPICAL_FUNCTIONS = ['count', 'distinct_count', 'mean', 'max', 'min', 'sum', +const DISPLAY_TYPICAL_FUNCTIONS = ['count', 'distinct_count', 'lat_long', 'mean', 'max', 'min', 'sum', 'median', 'varp', 'info_content', 'time']; // Returns a severity label (one of critical, major, minor, warning or unknown) diff --git a/x-pack/plugins/ml/common/util/job_utils.js b/x-pack/plugins/ml/common/util/job_utils.js index e6ce68706d209c..0cd006d8aed3ba 100644 --- a/x-pack/plugins/ml/common/util/job_utils.js +++ b/x-pack/plugins/ml/common/util/job_utils.js @@ -67,13 +67,14 @@ export function isTimeSeriesViewDetector(job, dtrIndex) { (dtr.partition_field_name !== 'mlcategory') && (dtr.over_field_name !== 'mlcategory'); - const usesScriptedFields = _.has(job, 'datafeed_config.script_fields'); - const scriptedFields = usesScriptedFields ? _.keys(job.datafeed_config.script_fields) : []; - if (isDetectorViewable === true && usesScriptedFields === true) { + const usesScriptFields = _.has(job, 'datafeed_config.script_fields'); + if (isDetectorViewable === true && usesScriptFields === true) { // Perform extra check to see if the detector is using a scripted field. - isDetectorViewable = (dtr.partition_field_name === undefined || scriptedFields.indexOf(dtr.partition_field_name) === -1) && - (dtr.by_field_name === undefined || scriptedFields.indexOf(dtr.by_field_name) === -1) && - (dtr.over_field_name === undefined || scriptedFields.indexOf(dtr.over_field_name) === -1); + const scriptFields = usesScriptFields ? _.keys(job.datafeed_config.script_fields) : []; + isDetectorViewable = scriptFields.indexOf(dtr.field_name) === -1 && + scriptFields.indexOf(dtr.partition_field_name) === -1 && + scriptFields.indexOf(dtr.by_field_name) === -1 && + scriptFields.indexOf(dtr.over_field_name) === -1; } } diff --git a/x-pack/plugins/ml/index.js b/x-pack/plugins/ml/index.js index 943a14b91b60d1..38a2ce773e65a1 100644 --- a/x-pack/plugins/ml/index.js +++ b/x-pack/plugins/ml/index.js @@ -20,6 +20,7 @@ import { dataRecognizer } from './server/routes/modules'; import { dataVisualizerRoutes } from './server/routes/data_visualizer'; import { calendars } from './server/routes/calendars'; import { fieldsService } from './server/routes/fields_service'; +import { resultsServiceRoutes } from './server/routes/results_service'; export const ml = (kibana) => { return new kibana.Plugin({ @@ -34,14 +35,9 @@ export const ml = (kibana) => { description: 'Machine Learning for the Elastic Stack', icon: 'plugins/ml/ml.svg', main: 'plugins/ml/app', - uses: [ - 'fieldFormats', - 'savedObjectTypes', - ] }, hacks: ['plugins/ml/hacks/toggle_app_link_in_nav'], home: ['plugins/ml/register_feature'] - }, @@ -87,6 +83,7 @@ export const ml = (kibana) => { dataVisualizerRoutes(server, commonRouteConfig); calendars(server, commonRouteConfig); fieldsService(server, commonRouteConfig); + resultsServiceRoutes(server, commonRouteConfig); } }); diff --git a/x-pack/plugins/ml/jsconfig.json b/x-pack/plugins/ml/jsconfig.json new file mode 100644 index 00000000000000..4ab033a2f8dcac --- /dev/null +++ b/x-pack/plugins/ml/jsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "baseUrl": "../../../.", + "paths": { + "ui/*": [ + "src/ui/public/*" + ], + "plugins/ml/*": [ + "x-pack/plugins/ml/public/*" + ] + } + }, + "exclude": [ + "node_modules", + "build" + ] +} diff --git a/x-pack/plugins/ml/public/app.js b/x-pack/plugins/ml/public/app.js index cb34a9ec85ee9f..ba1d17bdd9b8d8 100644 --- a/x-pack/plugins/ml/public/app.js +++ b/x-pack/plugins/ml/public/app.js @@ -5,6 +5,9 @@ */ +// import the uiExports that we want to "use" +import 'uiExports/fieldFormats'; +import 'uiExports/savedObjectTypes'; import 'ui/courier'; import 'ui-bootstrap'; @@ -24,6 +27,7 @@ import 'plugins/ml/explorer'; import 'plugins/ml/timeseriesexplorer'; import 'plugins/ml/components/form_label'; import 'plugins/ml/components/json_tooltip'; +import 'plugins/ml/components/tooltip'; import 'plugins/ml/components/confirm_modal'; import 'plugins/ml/components/nav_menu'; import 'plugins/ml/components/loading_indicator'; @@ -47,4 +51,3 @@ uiRoutes .otherwise({ redirectTo: '/jobs' }); - diff --git a/x-pack/plugins/ml/public/assets/app_ml.svg b/x-pack/plugins/ml/public/assets/app_ml.svg deleted file mode 100644 index ff87de25f17738..00000000000000 --- a/x-pack/plugins/ml/public/assets/app_ml.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.html b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.html deleted file mode 100644 index 913fbbab75133a..00000000000000 --- a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.html +++ /dev/null @@ -1,12 +0,0 @@ -
-
-

No matching results found

-
- - - - -
diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.js b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.js new file mode 100644 index 00000000000000..ef28da7ae23166 --- /dev/null +++ b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table.js @@ -0,0 +1,394 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + +/* + * React table for displaying a list of anomalies. + */ + +import PropTypes from 'prop-types'; +import _ from 'lodash'; +import $ from 'jquery'; + +import React, { + Component +} from 'react'; + +import { + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiHealth, + EuiInMemoryTable, + EuiText +} from '@elastic/eui'; + +import { formatDate } from '@elastic/eui/lib/services/format'; + +import { DescriptionCell } from './description_cell'; +import { EntityCell } from './entity_cell'; +import { InfluencersCell } from './influencers_cell'; +import { AnomalyDetails } from './anomaly_details'; +import { LinksMenu } from './links_menu'; + +import { mlAnomaliesTableService } from './anomalies_table_service'; +import { mlFieldFormatService } from 'plugins/ml/services/field_format_service'; +import { getSeverityColor } from 'plugins/ml/../common/util/anomaly_utils'; +import { formatValue } from 'plugins/ml/formatters/format_value'; + + +const INFLUENCERS_LIMIT = 5; // Maximum number of influencers to display before a 'show more' link is added. + + +function renderTime(date, aggregationInterval) { + if (aggregationInterval === 'hour') { + return formatDate(date, 'MMMM Do YYYY, HH:mm'); + } else if (aggregationInterval === 'second') { + return formatDate(date, 'MMMM Do YYYY, HH:mm:ss'); + } else { + return formatDate(date, 'MMMM Do YYYY'); + } +} + +function showLinksMenuForItem(item) { + return item.isTimeSeriesViewDetector || + item.entityName === 'mlcategory' || + item.customUrls !== undefined; +} + +function getColumns( + items, + examplesByJobId, + isAggregatedData, + interval, + timefilter, + showViewSeriesLink, + itemIdToExpandedRowMap, + toggleRow, + filter) { + const columns = [ + { + name: '', + render: (item) => ( + toggleRow(item)} + iconType={itemIdToExpandedRowMap[item.rowId] ? 'arrowDown' : 'arrowRight'} + aria-label={itemIdToExpandedRowMap[item.rowId] ? 'Hide details' : 'Show details'} + data-row-id={item.rowId} + /> + ) + }, + { + field: 'time', + name: 'time', + dataType: 'date', + render: (date) => renderTime(date, interval), + sortable: true + }, + { + field: 'severity', + name: `${(isAggregatedData === true) ? 'max ' : ''}severity`, + render: (score) => ( + + {score >= 1 ? Math.floor(score) : '< 1'} + + ), + sortable: true + }, + { + field: 'detector', + name: 'detector', + sortable: true + } + ]; + + if (items.some(item => item.entityValue !== undefined)) { + columns.push({ + field: 'entityValue', + name: 'found for', + render: (entityValue, item) => ( + + ), + sortable: true + }); + } + + if (items.some(item => item.influencers !== undefined)) { + columns.push({ + field: 'influencers', + name: 'influenced by', + render: (influencers) => ( + + ), + sortable: true + }); + } + + // Map the additional 'sort' fields to the actual, typical and description + // fields to ensure sorting is done correctly on the underlying metric value + // and not on e.g. the actual values array as a String. + if (items.some(item => item.actual !== undefined)) { + columns.push({ + field: 'actualSort', + name: 'actual', + render: (actual, item) => { + const fieldFormat = mlFieldFormatService.getFieldFormat(item.jobId, item.source.detector_index); + return formatValue(item.actual, item.source.function, fieldFormat); + }, + sortable: true + }); + } + + if (items.some(item => item.typical !== undefined)) { + columns.push({ + field: 'typicalSort', + name: 'typical', + render: (typical, item) => { + const fieldFormat = mlFieldFormatService.getFieldFormat(item.jobId, item.source.detector_index); + return formatValue(item.typical, item.source.function, fieldFormat); + }, + sortable: true + }); + + // Assume that if we are showing typical, there will be an actual too, + // so we can add a column to describe how actual compares to typical. + const nonTimeOfDayOrWeek = items.some((item) => { + const summaryRecFunc = item.source.function; + return summaryRecFunc !== 'time_of_day' && summaryRecFunc !== 'time_of_week'; + }); + if (nonTimeOfDayOrWeek === true) { + columns.push({ + field: 'metricDescriptionSort', + name: 'description', + render: (metricDescriptionSort, item) => ( + + ), + sortable: true + }); + } + } + + columns.push({ + field: 'jobId', + name: 'job ID', + sortable: true + }); + + const showExamples = items.some(item => item.entityName === 'mlcategory'); + const showLinks = (showViewSeriesLink === true) || items.some(item => showLinksMenuForItem(item)); + + if (showLinks === true) { + columns.push({ + name: 'links', + render: (item) => { + if (showLinksMenuForItem(item) === true) { + return ( + + ); + } else { + return null; + } + }, + sortable: false + }); + } + + if (showExamples === true) { + columns.push({ + name: 'category examples', + sortable: false, + truncateText: true, + render: (item) => { + const examples = _.get(examplesByJobId, [item.jobId, item.entityValue], []); + return ( + + {examples.map((example, i) => { + return {example}; + } + )} + + ); + } + }); + } + + return columns; +} + +class AnomaliesTable extends Component { + constructor(props) { + super(props); + + this.state = { + itemIdToExpandedRowMap: {} + }; + } + + isShowingAggregatedData = () => { + return (this.props.tableData.interval !== 'second'); + }; + + static getDerivedStateFromProps(nextProps, prevState) { + // Update the itemIdToExpandedRowMap state if a change to the table data has resulted + // in an anomaly that was previously expanded no longer being in the data. + const itemIdToExpandedRowMap = prevState.itemIdToExpandedRowMap; + const prevExpandedNotInData = Object.keys(itemIdToExpandedRowMap).find((rowId) => { + const matching = nextProps.tableData.anomalies.find((anomaly) => { + return anomaly.rowId === rowId; + }); + + return (matching === undefined); + }); + + if (prevExpandedNotInData !== undefined) { + // Anomaly data has changed and an anomaly that was previously expanded is no longer in the data. + return { + itemIdToExpandedRowMap: {} + }; + } + + // Return null to indicate no change to state. + return null; + } + + toggleRow = (item) => { + const itemIdToExpandedRowMap = { ...this.state.itemIdToExpandedRowMap }; + if (itemIdToExpandedRowMap[item.rowId]) { + delete itemIdToExpandedRowMap[item.rowId]; + } else { + const examples = (item.entityName === 'mlcategory') ? + _.get(this.props.tableData, ['examplesByJobId', item.jobId, item.entityValue]) : undefined; + itemIdToExpandedRowMap[item.rowId] = ( + + ); + } + this.setState({ itemIdToExpandedRowMap }); + }; + + onMouseOver = (event) => { + // Triggered when the mouse is somewhere over the table. + // Traverse through the table DOM to find the expand/collapse + // button which stores the ID of the row. + let mouseOverRecord = undefined; + const target = $(event.target); + const parentRow = target.closest('tr'); + const firstCell = parentRow.children('td').first(); + if (firstCell !== undefined) { + const expandButton = firstCell.find('button').first(); + if (expandButton.length > 0) { + const rowId = expandButton.attr('data-row-id'); + mouseOverRecord = this.props.tableData.anomalies.find((anomaly) => { + return (anomaly.rowId === rowId); + }); + } + } + + if (this.mouseOverRecord !== undefined) { + if (mouseOverRecord === undefined || this.mouseOverRecord.rowId !== mouseOverRecord.rowId) { + // Mouse is over a different row, fire mouseleave on the previous record. + mlAnomaliesTableService.anomalyRecordMouseleave.changed(this.mouseOverRecord); + + if (mouseOverRecord !== undefined) { + // Mouse is over a new row, fire mouseenter on the new record. + mlAnomaliesTableService.anomalyRecordMouseenter.changed(mouseOverRecord); + } + } + } else if (mouseOverRecord !== undefined) { + // Mouse is now over a row, fire mouseenter on the record. + mlAnomaliesTableService.anomalyRecordMouseenter.changed(mouseOverRecord); + } + + this.mouseOverRecord = mouseOverRecord; + }; + + onMouseLeave = () => { + if (this.mouseOverRecord !== undefined) { + mlAnomaliesTableService.anomalyRecordMouseleave.changed(this.mouseOverRecord); + } + }; + + render() { + const { timefilter, tableData, filter } = this.props; + + if (tableData === undefined || + tableData.anomalies === undefined || tableData.anomalies.length === 0) { + return ( + + + +

No matching anomalies found

+
+
+
+ ); + } + + const columns = getColumns( + tableData.anomalies, + tableData.examplesByJobId, + this.isShowingAggregatedData(), + tableData.interval, + timefilter, + tableData.showViewSeriesLink, + this.state.itemIdToExpandedRowMap, + this.toggleRow, + filter); + + const sorting = { + sort: { + field: 'severity', + direction: 'desc', + } + }; + + return ( + + ); + } +} +AnomaliesTable.propTypes = { + timefilter: PropTypes.object.isRequired, + tableData: PropTypes.object, + filter: PropTypes.func +}; + +export { AnomaliesTable }; diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_directive.js b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_directive.js index 6ef455aa04c106..3cfd962602a3b6 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_directive.js +++ b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_directive.js @@ -5,957 +5,26 @@ */ +import 'ngreact'; -/* - * AngularJS directive for rendering a table of Machine Learning anomalies. - */ - -import moment from 'moment'; -import _ from 'lodash'; -import rison from 'rison-node'; - -import { notify } from 'ui/notify'; -import { ES_FIELD_TYPES } from 'plugins/ml/../common/constants/field_types'; -import { parseInterval } from 'plugins/ml/../common/util/parse_interval'; -import { getUrlForRecord } from 'plugins/ml/util/custom_url_utils'; -import { replaceStringTokens, mlEscape } from 'plugins/ml/util/string_utils'; -import { isTimeSeriesViewDetector } from 'plugins/ml/../common/util/job_utils'; -import { - getEntityFieldName, - getEntityFieldValue, - showActualForFunction, - showTypicalForFunction, - getSeverity -} from 'plugins/ml/util/anomaly_utils'; -import { getFieldTypeFromMapping } from 'plugins/ml/services/mapping_service'; -import { ResultsServiceProvider } from 'plugins/ml/services/results_service'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; -import { FieldFormatServiceProvider } from 'plugins/ml/services/field_format_service'; -import template from './anomalies_table.html'; - -import 'plugins/ml/components/controls'; -import 'plugins/ml/components/paginated_table'; -import 'plugins/ml/filters/format_value'; -import 'plugins/ml/filters/metric_change_description'; -import './expanded_row/expanded_row_directive'; -import './influencers_cell/influencers_cell_directive'; - -import linkControlsHtml from './anomalies_table_links.html'; -import chrome from 'ui/chrome'; -import openRowArrow from 'plugins/ml/components/paginated_table/open.html'; import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - -module.directive('mlAnomaliesTable', function ( - $window, - $route, - timefilter, - Private, - mlAnomaliesTableService, - mlSelectIntervalService, - mlSelectSeverityService, - formatValueFilter) { - - return { - restrict: 'E', - scope: { - anomalyRecords: '=', - timeFieldName: '=', - showViewSeriesLink: '=', - filteringEnabled: '=' - }, - template, - link: function (scope, element) { - // Previously, we instantiated a new AppState here for the - // severity threshold and interval setting, thus resetting it on every - // reload. Now that this is handled differently via services and them - // being singletons, we need to explicitly reset the setting's state, - // otherwise the state would be retained across multiple instances of - // these settings. Should we want to change this behavior, e.g. to - // store the setting of the severity threshold across pages, we can - // just remove these resets. - mlSelectIntervalService.state.reset().changed(); - mlSelectSeverityService.state.reset().changed(); - const mlResultsService = Private(ResultsServiceProvider); - const mlJobService = Private(JobServiceProvider); - const mlFieldFormatService = Private(FieldFormatServiceProvider); - - scope.momentInterval = 'second'; - - scope.table = {}; - scope.table.perPage = 25; - scope.table.columns = []; - scope.table.rows = []; - scope.rowScopes = []; - - scope.influencersLimit = 5; - - scope.categoryExamplesByJob = {}; - const MAX_NUMBER_CATEGORY_EXAMPLES = 10; // Max number of examples to show in table cell or expanded row (engine default is to store 4). - - mlSelectIntervalService.state.watch(updateTableData); - mlSelectSeverityService.state.watch(updateTableData); - - scope.$on('renderTable', updateTableData); - - element.on('$destroy', () => { - mlSelectIntervalService.state.unwatch(updateTableData); - mlSelectSeverityService.state.unwatch(updateTableData); - scope.$destroy(); - }); - - scope.isShowingAggregatedData = function () { - const interval = mlSelectIntervalService.state.get('interval'); - return (interval.display !== 'Show all'); - }; - - scope.getExamplesForCategory = function (jobId, categoryId) { - return _.get(scope.categoryExamplesByJob, [jobId, categoryId], []); - }; - - scope.viewSeries = function (record) { - const bounds = timefilter.getActiveBounds(); - const from = bounds.min.toISOString(); // e.g. 2016-02-08T16:00:00.000Z - const to = bounds.max.toISOString(); - - // Zoom to show 50 buckets either side of the record. - const recordTime = moment(record[scope.timeFieldName]); - const zoomFrom = recordTime.subtract(50 * record.bucket_span, 's').toISOString(); - const zoomTo = recordTime.add(100 * record.bucket_span, 's').toISOString(); - - // Extract the by, over and partition fields for the record. - const entityCondition = {}; - - if (_.has(record, 'partition_field_value')) { - entityCondition[record.partition_field_name] = record.partition_field_value; - } - - if (_.has(record, 'over_field_value')) { - entityCondition[record.over_field_name] = record.over_field_value; - } - - if (_.has(record, 'by_field_value')) { - // Note that analyses with by and over fields, will have a top-level by_field_name, - // but the by_field_value(s) will be in the nested causes array. - // TODO - drilldown from cause in expanded row only? - entityCondition[record.by_field_name] = record.by_field_value; - } - - // Use rison to build the URL . - const _g = rison.encode({ - ml: { - jobIds: [record.job_id] - }, - refreshInterval: { - display: 'Off', - pause: false, - value: 0 - }, - time: { - from: from, - to: to, - mode: 'absolute' - } - }); - - const _a = rison.encode({ - mlTimeSeriesExplorer: { - zoom: { - from: zoomFrom, - to: zoomTo - }, - detectorIndex: record.detector_index, - entities: entityCondition, - }, - filters: [], - query: { - query_string: { - analyze_wildcard: true, - query: '*' - } - } - }); - - // Need to encode the _a parameter in case any entities contain unsafe characters such as '+'. - let path = chrome.getBasePath(); - path += '/app/ml#/timeseriesexplorer'; - path += '?_g=' + _g; - path += '&_a=' + encodeURIComponent(_a); - $window.open(path, '_blank'); - }; - - scope.viewExamples = function (record) { - const categoryId = getEntityFieldValue(record); - const job = mlJobService.getJob(record.job_id); - const categorizationFieldName = job.analysis_config.categorization_field_name; - const datafeedIndices = job.datafeed_config.indices; - // Find the type of the categorization field i.e. text (preferred) or keyword. - // Uses the first matching field found in the list of indices in the datafeed_config. - // attempt to load the field type using each index. we have to do it this way as _field_caps - // doesn't specify which index a field came from unless there is a clash. - let i = 0; - findFieldType(datafeedIndices[i]); - - function findFieldType(index) { - getFieldTypeFromMapping(index, categorizationFieldName) - .then((resp) => { - if (resp !== '') { - createAndOpenUrl(index, resp); - } else { - i++; - if (i < datafeedIndices.length) { - findFieldType(datafeedIndices[i]); - } else { - error(); - } - } - }) - .catch(() => { - error(); - }); - } - - function createAndOpenUrl(index, categorizationFieldType) { - // Find the ID of the index pattern with a title attribute which matches the - // index configured in the datafeed. If a Kibana index pattern has not been created - // for this index, then the user will see a warning message on the Discover tab advising - // them that no matching index pattern has been configured. - const indexPatterns = $route.current.locals.indexPatterns; - let indexPatternId = index; - for (let j = 0; j < indexPatterns.length; j++) { - if (indexPatterns[j].get('title') === index) { - indexPatternId = indexPatterns[j].id; - break; - } - } - - // Get the definition of the category and use the terms or regex to view the - // matching events in the Kibana Discover tab depending on whether the - // categorization field is of mapping type text (preferred) or keyword. - mlResultsService.getCategoryDefinition(record.job_id, categoryId) - .then((resp) => { - let query = null; - // Build query using categorization regex (if keyword type) or terms (if text type). - // Check for terms or regex in case categoryId represents an anomaly from the absence of the - // categorization field in documents (usually indicated by a categoryId of -1). - if (categorizationFieldType === ES_FIELD_TYPES.KEYWORD) { - if (resp.regex) { - query = `${categorizationFieldName}:/${resp.regex}/`; - } - } else { - if (resp.terms) { - query = `${categorizationFieldName}:` + resp.terms.split(' ').join(` AND ${categorizationFieldName}:`); - } - } - - const recordTime = moment(record[scope.timeFieldName]); - const from = recordTime.toISOString(); - const to = recordTime.add(record.bucket_span, 's').toISOString(); - - // Use rison to build the URL . - const _g = rison.encode({ - refreshInterval: { - display: 'Off', - pause: false, - value: 0 - }, - time: { - from: from, - to: to, - mode: 'absolute' - } - }); - - const appStateProps = { - index: indexPatternId, - filters: [] - }; - if (query !== null) { - appStateProps.query = { - query_string: { - analyze_wildcard: true, - query: query - } - }; - } - const _a = rison.encode(appStateProps); - - // Need to encode the _a parameter as it will contain characters such as '+' if using the regex. - let path = chrome.getBasePath(); - path += '/app/kibana#/discover'; - path += '?_g=' + _g; - path += '&_a=' + encodeURIComponent(_a); - $window.open(path, '_blank'); - - }).catch((resp) => { - console.log('viewExamples(): error loading categoryDefinition:', resp); - }); - - } - - function error() { - console.log(`viewExamples(): error finding type of field ${categorizationFieldName} in indices:`, - datafeedIndices); - notify.error(`Unable to view examples of documents with mlcategory ${categoryId} ` + - `as no mapping could be found for the categorization field ${categorizationFieldName}`, - { lifetime: 30000 }); - } - }; - - scope.openCustomUrl = function (customUrl, record) { - console.log('Anomalies Table - open customUrl for record:', customUrl, record); - - // If url_value contains $earliest$ and $latest$ tokens, add in times to the source record. - const timestamp = record[scope.timeFieldName]; - const configuredUrlValue = customUrl.url_value; - const timeRangeInterval = parseInterval(customUrl.time_range); - if (configuredUrlValue.includes('$earliest$')) { - let earliestMoment = moment(timestamp); - if (timeRangeInterval !== null) { - earliestMoment.subtract(timeRangeInterval); - } else { - earliestMoment = moment(timestamp).startOf(scope.momentInterval); - if (scope.momentInterval === 'hour') { - // Start from the previous hour. - earliestMoment.subtract(1, 'h'); - } - } - record.earliest = earliestMoment.toISOString(); // e.g. 2016-02-08T16:00:00.000Z - } - - if (configuredUrlValue.includes('$latest$')) { - let latestMoment = moment(timestamp).add(record.bucket_span, 's'); - if (timeRangeInterval !== null) { - latestMoment.add(timeRangeInterval); - } else { - if (scope.isShowingAggregatedData()) { - latestMoment = moment(timestamp).endOf(scope.momentInterval); - if (scope.momentInterval === 'hour') { - // Show to the end of the next hour. - latestMoment.add(1, 'h'); // e.g. 2016-02-08T18:59:59.999Z - } - } - } - record.latest = latestMoment.toISOString(); - } - - // If url_value contains $mlcategoryterms$ or $mlcategoryregex$, add in the - // terms and regex for the selected categoryId to the source record. - if ((configuredUrlValue.includes('$mlcategoryterms$') || configuredUrlValue.includes('$mlcategoryregex$')) - && _.has(record, 'mlcategory')) { - const jobId = record.job_id; - - // mlcategory in the source record will be an array - // - use first value (will only ever be more than one if influenced by category other than by/partition/over). - const categoryId = record.mlcategory[0]; - - mlResultsService.getCategoryDefinition(jobId, categoryId) - .then((resp) => { - // Prefix each of the terms with '+' so that the Elasticsearch Query String query - // run in a drilldown Kibana dashboard has to match on all terms. - const termsArray = _.map(resp.terms.split(' '), (term) => { return '+' + term; }); - record.mlcategoryterms = termsArray.join(' '); - record.mlcategoryregex = resp.regex; - - // Replace any tokens in the configured url_value with values from the source record, - // and then open link in a new tab/window. - const urlPath = replaceStringTokens(customUrl.url_value, record, true); - $window.open(urlPath, '_blank'); - - }).catch((resp) => { - console.log('openCustomUrl(): error loading categoryDefinition:', resp); - }); - - } else { - // Replace any tokens in the configured url_value with values from the source record, - // and then open link in a new tab/window. - const urlPath = getUrlForRecord(customUrl, record); - $window.open(urlPath, '_blank'); - } - - }; - - scope.filter = function (field, value, operator) { - mlAnomaliesTableService.filterChange.changed(field, value, operator); - }; - - function updateTableData() { - let summaryRecords = []; - if (scope.isShowingAggregatedData()) { - // Aggregate the anomaly data by time and detector, and entity (by/over). - summaryRecords = aggregateAnomalies(); - } else { - // Show all anomaly records. - const interval = mlSelectIntervalService.state.get('interval'); - scope.momentInterval = interval.val; - const threshold = mlSelectSeverityService.state.get('threshold'); - const filteredRecords = _.filter(scope.anomalyRecords, (record) => { - return Number(record.record_score) >= threshold.val; - }); - - _.each(filteredRecords, (record) => { - const detectorIndex = record.detector_index; - const jobId = record.job_id; - let detector = record.function_description; - if ((_.has(mlJobService.detectorsByJob, jobId)) && (detectorIndex < mlJobService.detectorsByJob[jobId].length)) { - detector = mlJobService.detectorsByJob[jobId][detectorIndex].detector_description; - } - - const displayRecord = { - 'time': record[scope.timeFieldName], - 'max severity': record.record_score, - 'detector': detector, - 'jobId': jobId, - 'source': record - }; - - const entityName = getEntityFieldName(record); - if (entityName !== undefined) { - displayRecord.entityName = entityName; - displayRecord.entityValue = getEntityFieldValue(record); - } - - if (_.has(record, 'partition_field_name')) { - displayRecord.partitionFieldName = record.partition_field_name; - displayRecord.partitionFieldValue = record.partition_field_value; - } - - if (_.has(record, 'influencers')) { - const influencers = []; - const sourceInfluencers = _.sortBy(record.influencers, 'influencer_field_name'); - _.each(sourceInfluencers, (influencer) => { - const influencerFieldName = influencer.influencer_field_name; - _.each(influencer.influencer_field_values, (influencerFieldValue) => { - const influencerToAdd = {}; - influencerToAdd[influencerFieldName] = influencerFieldValue; - influencers.push(influencerToAdd); - }); - }); - displayRecord.influencers = influencers; - } - - const functionDescription = _.get(record, 'function_description', ''); - if (showActualForFunction(functionDescription) === true) { - if (_.has(record, 'actual')) { - displayRecord.actual = record.actual; - } else { - // If only a single cause, copy values to the top level. - if (_.get(record, 'causes', []).length === 1) { - const cause = _.first(record.causes); - displayRecord.actual = cause.actual; - } - } - } - if (showTypicalForFunction(functionDescription) === true) { - if (_.has(record, 'typical')) { - displayRecord.typical = record.typical; - } else { - // If only a single cause, copy values to the top level. - if (_.get(record, 'causes', []).length === 1) { - const cause = _.first(record.causes); - displayRecord.typical = cause.typical; - } - } - } - - if (_.has(mlJobService.customUrlsByJob, jobId)) { - displayRecord.customUrls = mlJobService.customUrlsByJob[jobId]; - } - - summaryRecords.push(displayRecord); - - }); - } - - _.invoke(scope.rowScopes, '$destroy'); - scope.rowScopes.length = 0; - - const showExamples = _.some(summaryRecords, { 'entityName': 'mlcategory' }); - if (showExamples) { - // Obtain the list of categoryIds by jobId for which we need to obtain the examples. - // Note category examples will not be displayed if mlcategory is used just an - // influencer or as a partition field in a config with other by/over fields. - const categoryRecords = _.where(summaryRecords, { entityName: 'mlcategory' }); - const categoryIdsByJobId = {}; - _.each(categoryRecords, (record) => { - if (!_.has(categoryIdsByJobId, record.jobId)) { - categoryIdsByJobId[record.jobId] = []; - } - categoryIdsByJobId[record.jobId].push(record.entityValue); - }); - loadCategoryExamples(categoryIdsByJobId); - } else { - scope.categoryExamplesByJob = {}; - } - - // Only show columns in the table which exist in the results. - scope.table.columns = getPaginatedTableColumns(summaryRecords); - - // Sort by severity by default. - summaryRecords = (_.sortBy(summaryRecords, 'max severity')).reverse(); - scope.table.rows = summaryRecords.map((record) => { - return createTableRow(record); - }); - - } - - function aggregateAnomalies() { - // Aggregate the anomaly data by time, detector, and entity (by/over/partition). - // TODO - do we want to aggregate by job too, in cases where different jobs - // have detectors with the same description. - console.log('aggregateAnomalies(): number of anomalies to aggregate:', scope.anomalyRecords.length); - - if (scope.anomalyRecords.length === 0) { - return []; - } - - // Determine the aggregation interval - records in scope are in descending time order. - const interval = mlSelectIntervalService.state.get('interval'); - if (interval.val === 'auto') { - const earliest = moment(_.last(scope.anomalyRecords)[scope.timeFieldName]); - const latest = moment(_.first(scope.anomalyRecords)[scope.timeFieldName]); - const daysDiff = latest.diff(earliest, 'days'); - scope.momentInterval = (daysDiff < 2 ? 'hour' : 'day'); - } else { - scope.momentInterval = interval.val; - } - - // Only show records passing the severity threshold. - const threshold = mlSelectSeverityService.state.get('threshold'); - const filteredRecords = _.filter(scope.anomalyRecords, (record) => { - - return Number(record.record_score) >= threshold.val; - }); - - const aggregatedData = {}; - _.each(filteredRecords, (record) => { - - // Use moment.js to get start of interval. This will use browser timezone. - // TODO - support choice of browser or UTC timezone once functionality is in Kibana. - const roundedTime = moment(record[scope.timeFieldName]).startOf(scope.momentInterval).valueOf(); - if (!_.has(aggregatedData, roundedTime)) { - aggregatedData[roundedTime] = {}; - } - - // Aggregate by detector - default to functionDescription if no description available. - const detectorIndex = record.detector_index; - const jobId = record.job_id; - let detector = record.function_description; - if ((_.has(mlJobService.detectorsByJob, jobId)) && (detectorIndex < mlJobService.detectorsByJob[jobId].length)) { - detector = mlJobService.detectorsByJob[jobId][detectorIndex].detector_description; - } - const detectorsAtTime = aggregatedData[roundedTime]; - if (!_.has(detectorsAtTime, detector)) { - detectorsAtTime[detector] = {}; - } - - // Now add an object for the anomaly with the highest anomaly score per entity. - // For the choice of entity, look in order for byField, overField, partitionField. - // If no by/over/partition, default to an empty String. - const entitiesForDetector = detectorsAtTime[detector]; - - // TODO - are we worried about different byFields having the same - // value e.g. host=server1 and machine=server1? - let entity = getEntityFieldValue(record); - if (entity === undefined) { - entity = ''; - } - if (!_.has(entitiesForDetector, entity)) { - entitiesForDetector[entity] = record; - } else { - const score = record.record_score; - if (score > entitiesForDetector[entity].record_score) { - entitiesForDetector[entity] = record; - } - } - }); - - console.log('aggregateAnomalies() aggregatedData is:', aggregatedData); - - // Flatten the aggregatedData to give a list of records with the highest score per bucketed time / detector. - const summaryRecords = []; - _.each(aggregatedData, (timeDetectors, roundedTime) => { - _.each(timeDetectors, (entityDetectors, detector) => { - _.each(entityDetectors, (record, entity) => { - const displayRecord = { - 'time': +roundedTime, - 'max severity': record.record_score, - 'detector': detector, - 'jobId': record.job_id, - 'source': record - }; - - const entityName = getEntityFieldName(record); - if (entityName !== undefined) { - displayRecord.entityName = entityName; - displayRecord.entityValue = entity; - } - - if (_.has(record, 'partition_field_name')) { - displayRecord.partitionFieldName = record.partition_field_name; - displayRecord.partitionFieldValue = record.partition_field_value; - } - - if (_.has(record, 'influencers')) { - const influencers = []; - const sourceInfluencers = _.sortBy(record.influencers, 'influencer_field_name'); - _.each(sourceInfluencers, (influencer) => { - const influencerFieldName = influencer.influencer_field_name; - _.each(influencer.influencer_field_values, (influencerFieldValue) => { - const influencerToAdd = {}; - influencerToAdd[influencerFieldName] = influencerFieldValue; - influencers.push(influencerToAdd); - }); - }); - displayRecord.influencers = influencers; - } - - // Copy actual and typical values to the top level for display. - const functionDescription = _.get(record, 'function_description', ''); - if (showActualForFunction(functionDescription) === true) { - if (_.has(record, 'actual')) { - displayRecord.actual = record.actual; - } else { - // If only a single cause, copy value to the top level. - if (_.get(record, 'causes', []).length === 1) { - const cause = _.first(record.causes); - displayRecord.actual = cause.actual; - } - } - } - if (showTypicalForFunction(functionDescription) === true) { - if (_.has(record, 'typical')) { - displayRecord.typical = record.typical; - } else { - // If only a single cause, copy value to the top level. - if (_.get(record, 'causes', []).length === 1) { - const cause = _.first(record.causes); - displayRecord.typical = cause.typical; - } - } - } - - if (_.has(mlJobService.customUrlsByJob, record.job_id)) { - displayRecord.customUrls = mlJobService.customUrlsByJob[record.job_id]; - } - - summaryRecords.push(displayRecord); - - }); - }); - }); - - return summaryRecords; - - } - - function getPaginatedTableColumns(summaryRecords) { - // Builds the list of columns for use in the paginated table: - // row expand arrow - // time - // max severity - // detector - // found for (if by/over/partition) - // influenced by (if influencers) - // actual - // typical - // description (how actual compares to typical) - // job_id - // links (if custom URLs configured or drilldown functionality) - // category examples (if by mlcategory) - const paginatedTableColumns = [ - { title: '', sortable: false, class: 'col-expand-arrow' }, - { title: 'time', sortable: true }]; - - if (scope.isShowingAggregatedData()) { - paginatedTableColumns.push({ title: 'max severity', sortable: true }); - } else { - paginatedTableColumns.push({ title: 'severity', sortable: true }); - } - - paginatedTableColumns.push({ title: 'detector', sortable: true }); - - const showEntity = _.some(summaryRecords, 'entityValue'); - const showInfluencers = _.some(summaryRecords, 'influencers'); - const showActual = _.some(summaryRecords, 'actual'); - const showTypical = _.some(summaryRecords, 'typical'); - const showExamples = _.some(summaryRecords, { 'entityName': 'mlcategory' }); - const showLinks = ((scope.showViewSeriesLink === true) && - _.some(summaryRecords, (record) => { - const job = mlJobService.getJob(record.jobId); - return isTimeSeriesViewDetector(job, record.source.detector_index); - })) || showExamples === true || _.some(summaryRecords, 'customUrls'); - - if (showEntity === true) { - paginatedTableColumns.push({ title: 'found for', sortable: true }); - } - if (showInfluencers === true) { - paginatedTableColumns.push({ title: 'influenced by', sortable: true }); - } - if (showActual === true) { - paginatedTableColumns.push({ title: 'actual', sortable: true }); - } - if (showTypical === true) { - paginatedTableColumns.push({ title: 'typical', sortable: true }); - - // Assume that if we are showing typical, there will be an actual too, - // so we can add a column to describe how actual compares to typical. - const nonTimeOfDayOrWeek = _.some(summaryRecords, (record) => { - const summaryRecFunc = record.source.function; - return summaryRecFunc !== 'time_of_day' && summaryRecFunc !== 'time_of_week'; - }); - if (nonTimeOfDayOrWeek === true) { - paginatedTableColumns.push({ title: 'description', sortable: true }); - } - } - paginatedTableColumns.push({ title: 'job ID', sortable: true }); - if (showLinks === true) { - paginatedTableColumns.push({ title: 'links', sortable: false }); - } - if (showExamples === true) { - paginatedTableColumns.push({ title: 'category examples', sortable: false }); - } - - return paginatedTableColumns; - } - - - function createTableRow(record) { - const rowScope = scope.$new(); - rowScope.expandable = true; - rowScope.expandElement = 'ml-anomalies-table-expanded-row'; - rowScope.record = record; - rowScope.isShowingAggregatedData = scope.isShowingAggregatedData(); - - rowScope.initRow = function () { - if (_.has(record, 'entityValue') && record.entityName === 'mlcategory') { - // Obtain the category definition and display the examples in the expanded row. - mlResultsService.getCategoryDefinition(record.jobId, record.entityValue) - .then((resp) => { - rowScope.categoryDefinition = { - 'examples': _.slice(resp.examples, 0, Math.min(resp.examples.length, MAX_NUMBER_CATEGORY_EXAMPLES)) }; - }).catch((resp) => { - console.log('Anomalies table createTableRow(): error loading categoryDefinition:', resp); - }); - } - - rowScope.$broadcast('initRow', record); - }; - - rowScope.mouseenterRow = function () { - // Publish that a record is being hovered over, so that the corresponding marker - // in the model plot chart can be highlighted. - mlAnomaliesTableService.anomalyRecordMouseenter.changed(record); - }; - - rowScope.mouseleaveRow = function () { - // Publish that a record is no longer being hovered over, so that the corresponding marker in the - // model plot chart can be unhighlighted. - mlAnomaliesTableService.anomalyRecordMouseleave.changed(record); - }; - - // Create a table row with the following columns: - // row expand arrow - // time - // max severity - // detector - // found for (if by/over/partition) - // influenced by (if influencers) - // actual - // typical - // description (how actual compares to typical) - // job_id - // links (if customUrls configured or drilldown to Single Metric) - // category examples (if by mlcategory) - const addEntity = _.findWhere(scope.table.columns, { 'title': 'found for' }); - const addInfluencers = _.findWhere(scope.table.columns, { 'title': 'influenced by' }); - - const addActual = _.findWhere(scope.table.columns, { 'title': 'actual' }); - const addTypical = _.findWhere(scope.table.columns, { 'title': 'typical' }); - const addDescription = _.findWhere(scope.table.columns, { 'title': 'description' }); - const addExamples = _.findWhere(scope.table.columns, { 'title': 'category examples' }); - const addLinks = _.findWhere(scope.table.columns, { 'title': 'links' }); - const fieldFormat = mlFieldFormatService.getFieldFormat(record.jobId, record.source.detector_index); - - const tableRow = [ - { - markup: openRowArrow, - scope: rowScope - }, - { - markup: formatTimestamp(record.time), - value: record.time - }, - { - markup: parseInt(record['max severity']) >= 1 ? - ' ' + Math.floor(record['max severity']) : - ' < 1', - value: record['max severity'] - }, - { - markup: mlEscape(record.detector), - value: record.detector - } - ]; - - if (addEntity !== undefined) { - if (_.has(record, 'entityValue')) { - if (record.entityName !== 'mlcategory') { - // Escape single quotes and backslash characters in the HTML for the event handlers. - const safeEntityName = mlEscape(record.entityName.replace(/(['\\])/g, '\\$1')); - const safeEntityValue = mlEscape(record.entityValue.replace(/(['\\])/g, '\\$1')); - - tableRow.push({ - markup: mlEscape(record.entityValue) + - ' ' + - ' ', - value: record.entityValue, - scope: rowScope - }); - } else { - tableRow.push({ - markup: 'mlcategory ' + record.entityValue, - value: record.entityValue - }); - } - } else { - tableRow.push({ - markup: '', - value: '' - }); - } - } - - if (addInfluencers !== undefined) { - if (_.has(record, 'influencers')) { - const cellMarkup = ``; - tableRow.push({ - markup: cellMarkup, - value: cellMarkup, - scope: rowScope - }); - } else { - tableRow.push({ - markup: '', - value: '' - }); - } - } - - if (addActual !== undefined) { - if (_.has(record, 'actual')) { - tableRow.push({ - markup: formatValueFilter(record.actual, record.source.function, fieldFormat), - // Store the unformatted value as a number so that sorting works correctly. - value: Number(record.actual), - scope: rowScope }); - } else { - tableRow.push({ markup: '', value: '' }); - } - } - if (addTypical !== undefined) { - if (_.has(record, 'typical')) { - const typicalVal = Number(record.typical); - tableRow.push({ - markup: formatValueFilter(record.typical, record.source.function, fieldFormat), - value: typicalVal, - scope: rowScope }); - - if (addDescription !== undefined) { - // Assume there is an actual value if there is a typical, - // and add a description cell if not time_of_week/day. - const detectorFunc = record.source.function; - if (detectorFunc !== 'time_of_week' && detectorFunc !== 'time_of_day') { - const actualVal = Number(record.actual); - const factor = (actualVal > typicalVal) ? actualVal / typicalVal : typicalVal / actualVal; - tableRow.push({ - markup: ``, - value: Math.abs(factor), - scope: rowScope }); - } else { - tableRow.push({ markup: '', value: '' }); - } - } - } else { - tableRow.push({ markup: '', value: '' }); - if (addDescription !== undefined) { - tableRow.push({ markup: '', value: '' }); - } - } - } - - tableRow.push({ markup: record.jobId, value: record.jobId }); - - if (addLinks !== undefined) { - const job = mlJobService.getJob(record.jobId); - rowScope.showViewSeriesLink = scope.showViewSeriesLink === true && - isTimeSeriesViewDetector(job, record.source.detector_index); - rowScope.showViewExamplesLink = (_.get(record, 'entityName') === 'mlcategory'); - if (_.has(record, 'customUrls') || rowScope.showViewSeriesLink === true - || rowScope.showViewExamplesLink) { - rowScope.customUrls = record.customUrls; - rowScope.source = record.source; - - tableRow.push({ - markup: linkControlsHtml, - scope: rowScope - }); - } else { - tableRow.push({ - markup: '', - value: '' - }); - } - } - - if (addExamples !== undefined) { - if (record.entityName === 'mlcategory') { - tableRow.push({ markup: '{{item}}', scope: rowScope }); - } else { - tableRow.push({ markup: '', value: '' }); - } - } - - scope.rowScopes.push(rowScope); - - return tableRow; - - } - - function loadCategoryExamples(categoryIdsByJobId) { - // Load the example events for the specified map of job_ids and categoryIds from Elasticsearch. - scope.categoryExamplesByJob = {}; - _.each(categoryIdsByJobId, (categoryIds, jobId) => { - mlResultsService.getCategoryExamples(jobId, categoryIds, MAX_NUMBER_CATEGORY_EXAMPLES) - .then((resp) => { - scope.categoryExamplesByJob[jobId] = resp.examplesByCategoryId; - }).catch((resp) => { - console.log('Anomalies table - error getting category examples:', resp); - }); - }); - } - - function formatTimestamp(epochMs) { - const time = moment(epochMs); - if (scope.momentInterval === 'hour') { - return time.format('MMMM Do YYYY, HH:mm'); - } else if (scope.momentInterval === 'second') { - return time.format('MMMM Do YYYY, HH:mm:ss'); - } else { - return time.format('MMMM Do YYYY'); - } - } - +const module = uiModules.get('apps/ml', ['react']); + +import { AnomaliesTable } from './anomalies_table'; + +module.directive('mlAnomaliesTable', function ($injector) { + const timefilter = $injector.get('timefilter'); + const reactDirective = $injector.get('reactDirective'); + + return reactDirective( + AnomaliesTable, + [ + ['filter', { watchDepth: 'reference' }], + ['tableData', { watchDepth: 'reference' }] + ], + { restrict: 'E' }, + { + timefilter } - }; + ); }); diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_links.html b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_links.html deleted file mode 100644 index f6576d233d7325..00000000000000 --- a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_links.html +++ /dev/null @@ -1,20 +0,0 @@ - - diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_service.js b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_service.js index bfdecbad968860..2c7147650c221d 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_service.js +++ b/x-pack/plugins/ml/public/components/anomalies_table/anomalies_table_service.js @@ -11,16 +11,14 @@ * anomalies table component. */ -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - import { listenerFactoryProvider } from 'plugins/ml/factories/listener_factory'; -module.service('mlAnomaliesTableService', function () { - - const listenerFactory = listenerFactoryProvider(); - this.anomalyRecordMouseenter = listenerFactory(); - this.anomalyRecordMouseleave = listenerFactory(); - this.filterChange = listenerFactory(); +class AnomaliesTableService { + constructor() { + const listenerFactory = listenerFactoryProvider(); + this.anomalyRecordMouseenter = listenerFactory(); + this.anomalyRecordMouseleave = listenerFactory(); + } +} -}); +export const mlAnomaliesTableService = new AnomaliesTableService(); diff --git a/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.js b/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.js new file mode 100644 index 00000000000000..fdd12e1e596062 --- /dev/null +++ b/x-pack/plugins/ml/public/components/anomalies_table/anomaly_details.js @@ -0,0 +1,326 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + +/* + * React component for displaying details of an anomaly in the expanded row section + * of the anomalies table. + */ + +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import _ from 'lodash'; + +import { + EuiDescriptionList, + EuiIcon, + EuiLink, + EuiSpacer, + EuiText +} from '@elastic/eui'; +import { formatDate } from '@elastic/eui/lib/services/format'; + +import { EntityCell } from './entity_cell'; +import { + getSeverity, + showActualForFunction, + showTypicalForFunction +} from 'plugins/ml/../common/util/anomaly_utils'; +import { formatValue } from 'plugins/ml/formatters/format_value'; + +const TIME_FIELD_NAME = 'timestamp'; + + +function getFilterEntity(entityName, entityValue, filter) { + return ( + + ); +} + +function getDetailsItems(anomaly, examples, filter) { + const source = anomaly.source; + + // TODO - when multivariate analyses are more common, + // look in each cause for a 'correlatedByFieldValue' field, + let causes = []; + const sourceCauses = source.causes || []; + let singleCauseByFieldName = undefined; + let singleCauseByFieldValue = undefined; + if (sourceCauses.length === 1) { + // Metrics and probability will already have been placed at the top level. + // If cause has byFieldValue, move it to a top level fields for display. + if (sourceCauses[0].by_field_name !== undefined) { + singleCauseByFieldName = sourceCauses[0].by_field_name; + singleCauseByFieldValue = sourceCauses[0].by_field_value; + } + } else { + causes = sourceCauses.map((cause) => { + const simplified = _.pick(cause, 'typical', 'actual', 'probability'); + // Get the 'entity field name/value' to display in the cause - + // For by and over, use by_field_name/value (over_field_name/value are in the top level fields) + // For just an 'over' field - the over_field_name/value appear in both top level and cause. + simplified.entityName = _.has(cause, 'by_field_name') ? cause.by_field_name : cause.over_field_name; + simplified.entityValue = _.has(cause, 'by_field_value') ? cause.by_field_value : cause.over_field_value; + return simplified; + }); + } + + const items = []; + if (source.partition_field_value !== undefined) { + items.push({ + title: source.partition_field_name, + description: getFilterEntity(source.partition_field_name, source.partition_field_value, filter) + }); + } + + if (source.by_field_value !== undefined) { + items.push({ + title: source.by_field_name, + description: getFilterEntity(source.by_field_name, source.by_field_value, filter) + }); + } + + if (singleCauseByFieldName !== undefined) { + // Display byField of single cause. + items.push({ + title: singleCauseByFieldName, + description: getFilterEntity(singleCauseByFieldName, singleCauseByFieldValue, filter) + }); + } + + if (source.over_field_value !== undefined) { + items.push({ + title: source.over_field_name, + description: getFilterEntity(source.over_field_name, source.over_field_value, filter) + }); + } + + const anomalyTime = source[TIME_FIELD_NAME]; + let timeDesc = `${formatDate(anomalyTime, 'MMMM Do YYYY, HH:mm:ss')}`; + if (source.bucket_span !== undefined) { + const anomalyEndTime = anomalyTime + (source.bucket_span * 1000); + timeDesc += ` to ${formatDate(anomalyEndTime, 'MMMM Do YYYY, HH:mm:ss')}`; + } + items.push({ + title: 'time', + description: timeDesc + }); + + if (examples !== undefined && examples.length > 0) { + examples.forEach((example, index) => { + const title = (index === 0) ? 'category examples' : ''; + items.push({ title, description: example }); + }); + } + + items.push({ + title: 'function', + description: (source.function !== 'metric') ? source.function : source.function_description + }); + + if (source.field_name !== undefined) { + items.push({ + title: 'fieldName', + description: source.field_name + }); + } + + const functionDescription = source.function_description || ''; + if (anomaly.actual !== undefined && showActualForFunction(functionDescription) === true) { + items.push({ + title: 'actual', + description: formatValue(anomaly.actual, source.function) + }); + } + + if (anomaly.typical !== undefined && showTypicalForFunction(functionDescription) === true) { + items.push({ + title: 'typical', + description: formatValue(anomaly.typical, source.function) + }); + } + + items.push({ + title: 'job ID', + description: anomaly.jobId + }); + + items.push({ + title: 'probability', + description: source.probability + }); + + // If there was only one cause, the actual, typical and by_field + // will already have been added for display. + if (causes.length > 1) { + causes.forEach((cause, index) => { + const title = (index === 0) ? `${cause.entityName} values` : ''; + let description = `${cause.entityValue} (actual ${formatValue(cause.actual, source.function)}, `; + description += `typical ${formatValue(cause.typical, source.function)}, probability ${cause.probability})`; + items.push({ title, description }); + }); + } + + return items; +} + +export class AnomalyDetails extends Component { + + constructor(props) { + super(props); + this.state = { + showAllInfluencers: false + }; + } + + toggleAllInfluencers() { + this.setState({ showAllInfluencers: !this.state.showAllInfluencers }); + } + + renderDescription() { + const anomaly = this.props.anomaly; + const source = anomaly.source; + + let anomalyDescription = `${getSeverity(anomaly.severity)} anomaly in ${anomaly.detector}`; + if (anomaly.entityName !== undefined) { + anomalyDescription += ` found for ${anomaly.entityName} ${anomaly.entityValue}`; + } + + if ((source.partition_field_name !== undefined) && + (source.partition_field_name !== anomaly.entityName)) { + anomalyDescription += ` detected in ${source.partition_field_name}`; + anomalyDescription += ` ${source.partition_field_value}`; + } + + // Check for a correlatedByFieldValue in the source which will be present for multivariate analyses + // where the record is anomalous due to relationship with another 'by' field value. + let mvDescription = undefined; + if (source.correlated_by_field_value !== undefined) { + mvDescription = `multivariate correlations found in ${source.by_field_name}; `; + mvDescription += `${source.by_field_value} is considered anomalous given ${source.correlated_by_field_value}`; + } + return ( + + +
Description
+ {anomalyDescription} +
+ {(mvDescription !== undefined) && + + {mvDescription} + + } +
+ ); + } + + renderDetails() { + const detailItems = getDetailsItems(this.props.anomaly, this.props.examples, this.props.filter); + const isInterimResult = _.get(this.props.anomaly, 'source.is_interim', false); + return ( + + + {this.props.isAggregatedData === true ? ( +
Details on highest severity anomaly
+ ) : ( +
Anomaly details
+ )} + {isInterimResult === true && + + Interim result + + } +
+ +
+ ); + } + + renderInfluencers() { + const anomalyInfluencers = this.props.anomaly.influencers; + const listItems = []; + let othersCount = 0; + let numToDisplay = 0; + if (anomalyInfluencers !== undefined) { + numToDisplay = (this.state.showAllInfluencers === true) ? + anomalyInfluencers.length : Math.min(this.props.influencersLimit, anomalyInfluencers.length); + othersCount = Math.max(anomalyInfluencers.length - numToDisplay, 0); + + if (othersCount === 1) { + // Display the 1 extra influencer as displaying "and 1 more" would also take up a line. + numToDisplay++; + othersCount = 0; + } + + for (let i = 0; i < numToDisplay; i++) { + Object.keys(anomalyInfluencers[i]).forEach((influencerFieldName) => { + listItems.push({ + title: influencerFieldName, + description: anomalyInfluencers[i][influencerFieldName] + }); + }); + } + } + + if (listItems.length > 0) { + return ( + + + +
Influencers
+
+ + {othersCount > 0 && + this.toggleAllInfluencers()} + > + and {othersCount} more + + } + {numToDisplay > (this.props.influencersLimit + 1) && + this.toggleAllInfluencers()} + > + show less + + } +
+ ); + } + } + + render() { + + return ( +
+ {this.renderDescription()} + + {this.renderDetails()} + {this.renderInfluencers()} +
+ ); + } +} + +AnomalyDetails.propTypes = { + anomaly: PropTypes.object.isRequired, + examples: PropTypes.array, + isAggregatedData: PropTypes.bool, + filter: PropTypes.func, + influencersLimit: PropTypes.number +}; diff --git a/x-pack/plugins/ml/public/components/anomalies_table/description_cell.js b/x-pack/plugins/ml/public/components/anomalies_table/description_cell.js new file mode 100644 index 00000000000000..034bb905aef46f --- /dev/null +++ b/x-pack/plugins/ml/public/components/anomalies_table/description_cell.js @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + +import PropTypes from 'prop-types'; +import React from 'react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiText +} from '@elastic/eui'; + +import { getMetricChangeDescription } from 'plugins/ml/formatters/metric_change_description'; + +/* + * Component for rendering the description cell in the anomalies table, which provides a + * concise description of how the actual value of an anomaly compares to the typical value. + */ +export function DescriptionCell({ actual, typical }) { + + const { + iconType, + message + } = getMetricChangeDescription(actual, typical); + + return ( + + {iconType !== undefined && + + + + } + + +

{message}

+
+
+
+ ); +} + +DescriptionCell.propTypes = { + actual: PropTypes.oneOfType([PropTypes.array, PropTypes.number]), + typical: PropTypes.oneOfType([PropTypes.array, PropTypes.number]) +}; diff --git a/x-pack/plugins/ml/public/components/anomalies_table/entity_cell.js b/x-pack/plugins/ml/public/components/anomalies_table/entity_cell.js new file mode 100644 index 00000000000000..ca6d3cf7e68cd9 --- /dev/null +++ b/x-pack/plugins/ml/public/components/anomalies_table/entity_cell.js @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + +import PropTypes from 'prop-types'; +import React from 'react'; + +import { + EuiButtonIcon, + EuiToolTip +} from '@elastic/eui'; + +/* + * Component for rendering an entity cell in the anomalies table, displaying the value + * of the 'partition', 'by' or 'over' field, and optionally links for adding or removing + * a filter on this entity. + */ +export function EntityCell({ entityName, entityValue, filter }) { + const valueText = (entityName !== 'mlcategory') ? entityValue : `mlcategory ${entityValue}`; + return ( + + {valueText} + {filter !== undefined && entityName !== undefined && entityValue !== undefined && + + + filter(entityName, entityValue, '+')} + iconType="plusInCircle" + aria-label="Add filter" + /> + + + filter(entityName, entityValue, '-')} + iconType="minusInCircle" + aria-label="Remove filter" + /> + + + } + + ); +} + +EntityCell.propTypes = { + entityName: PropTypes.string, + entityValue: PropTypes.any, + filter: PropTypes.func +}; diff --git a/x-pack/plugins/ml/public/components/anomalies_table/expanded_row/expanded_row.html b/x-pack/plugins/ml/public/components/anomalies_table/expanded_row/expanded_row.html deleted file mode 100644 index df613ab198fafa..00000000000000 --- a/x-pack/plugins/ml/public/components/anomalies_table/expanded_row/expanded_row.html +++ /dev/null @@ -1,108 +0,0 @@ -
- Description: - {{description}} - {{multiVariateDescription}} - - Details on highest severity anomaly: - Anomaly Details: -
Interim result
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{{record.source.partition_field_name}}:{{record.source.partition_field_value}} - - -
{{record.source.by_field_name}}:{{record.source.by_field_value}} - - -
{{singleCauseByFieldName}}:{{singleCauseByFieldValue}} - - -
{{record.source.over_field_name}}:{{record.source.over_field_value}} - - -
time:{{anomalyTime}} to {{anomalyEndTime}}
time:{{anomalyTime}}
category examples: {{example}}
function:{{record.source.function}}{{record.source.function_description}}
fieldName:{{record.source.field_name}}
actual:{{actual | formatValue:record.source.function}}
typical:{{typical | formatValue:record.source.function}}
job ID:{{record.jobId}} -
probability:{{record.source.probability}}
{{cause.entityName}} values: {{cause.entityValue}} (actual {{cause.actual | formatValue:record.source.function}}, typical {{cause.typical | formatValue:record.source.function}}, probability {{cause.probability}})
- - Influenced by: - - - - - - - - - - - -
{{influencer.name}}{{influencer.value}}
- -
- -
- -
diff --git a/x-pack/plugins/ml/public/components/anomalies_table/expanded_row/expanded_row_directive.js b/x-pack/plugins/ml/public/components/anomalies_table/expanded_row/expanded_row_directive.js deleted file mode 100644 index 64d65d1360bb3a..00000000000000 --- a/x-pack/plugins/ml/public/components/anomalies_table/expanded_row/expanded_row_directive.js +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -/* - * Angular directive for rendering the expanded row content in the - * Machine Learning anomalies table. It displays more details on the - * anomaly summarized in the row, including field names, - * actual and typical values for the analyzed metric, - * plus causes and examples events according to the detector configuration. - */ - -import _ from 'lodash'; -import moment from 'moment'; - -import template from './expanded_row.html'; -import { - getSeverity, - showActualForFunction, - showTypicalForFunction -} from 'plugins/ml/util/anomaly_utils'; -import 'plugins/ml/filters/format_value'; - -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - -module.directive('mlAnomaliesTableExpandedRow', function () { - - function link(scope) { - scope.record = scope.$parent.record; - scope.filter = scope.$parent.filter; - scope.filteringEnabled = scope.$parent.filteringEnabled; - scope.isShowingAggregatedData = scope.$parent.isShowingAggregatedData; - scope.influencersLimit = scope.$parent.influencersLimit; - scope.influencersNumToDislay = scope.influencersLimit; - - const timeFieldName = 'timestamp'; - const momentTime = moment(scope.record.source[timeFieldName]); - scope.anomalyTime = momentTime.format('MMMM Do YYYY, HH:mm:ss'); - if (_.has(scope.record.source, 'bucket_span')) { - scope.anomalyEndTime = momentTime.add(scope.record.source.bucket_span, 's').format('MMMM Do YYYY, HH:mm:ss'); - } - - scope.$on('initRow', () => { - // Only build the description and details on metric values, - // causes and influencers when the row is first expanded. - buildContent(); - }); - - scope.toggleAllInfluencers = function () { - if (_.has(scope.record, 'influencers')) { - const recordInfluencers = scope.record.influencers; - if (scope.influencers.length === recordInfluencers.length) { - scope.influencersNumToDislay = scope.influencersLimit; - } else { - scope.influencersNumToDislay = recordInfluencers.length; - } - buildInfluencers(); - } - }; - - if (scope.$parent.open === true) { - // Build the content if the row was already open before re-render (e.g. when sorting), - buildContent(); - } - - if (_.has(scope.record, 'entityValue') && scope.record.entityName === 'mlcategory') { - // For categorization results, controller will obtain the definition when the - // row is first expanded and place the categoryDefinition in the row scope. - const unbindWatch = scope.$parent.$watch('categoryDefinition', (categoryDefinition) => { - if (categoryDefinition !== undefined) { - scope.examples = categoryDefinition.examples; - unbindWatch(); - } - }); - } - - function buildContent() { - buildDescription(); - buildMetrics(); - buildCauses(); - buildInfluencers(); - } - - function buildDescription() { - const record = scope.record; - let rowDescription = getSeverity(record.source.record_score) + ' anomaly in ' + record.detector; - - if (_.has(record, 'entityName')) { - rowDescription += ' found for ' + record.entityName; - rowDescription += ' '; - rowDescription += record.entityValue; - } - - if (_.has(record.source, 'partition_field_name') && (record.source.partition_field_name !== record.entityName)) { - rowDescription += ' detected in ' + record.source.partition_field_name; - rowDescription += ' '; - rowDescription += record.source.partition_field_value; - } - - scope.description = rowDescription; - - // Check for a correlatedByFieldValue in the source which will be present for multivariate analyses - // where the record is anomalous due to relationship with another 'by' field value. - if (_.has(record.source, 'correlated_by_field_value')) { - let mvDescription = 'multivariate correlations found in '; - mvDescription += record.source.by_field_name; - mvDescription += '; '; - mvDescription += record.source.by_field_value; - mvDescription += ' is considered anomalous given '; - mvDescription += record.source.correlated_by_field_value; - scope.multiVariateDescription = mvDescription; - } - - - // Display a warning below the description if the record is an interim result. - scope.isInterim = _.get(record, 'source.is_interim', false); - } - - function buildMetrics() { - const record = scope.record; - const functionDescription = _.get(record, 'source.function_description', ''); - if (showActualForFunction(functionDescription) === true) { - if (!_.has(scope.record.source, 'causes')) { - scope.actual = record.source.actual; - } else { - const causes = scope.record.source.causes; - if (causes.length === 1) { - // If only one 'cause', move value to top level. - const cause = _.first(causes); - scope.actual = cause.actual; - } - } - } - if (showTypicalForFunction(functionDescription) === true) { - if (!_.has(scope.record.source, 'causes')) { - scope.typical = record.source.typical; - } else { - const causes = scope.record.source.causes; - if (causes.length === 1) { - // If only one 'cause', move value to top level. - const cause = _.first(causes); - scope.typical = cause.typical; - } - } - } - } - - function buildCauses() { - if (_.has(scope.record.source, 'causes')) { - const causes = scope.record.source.causes; - - // TODO - build different information depending on whether function is rare, freq_rare or another. - - // TODO - look in each cause for a 'correlatedByFieldValue' field, - // and if so, add to causes scope object for rendering in the template. - if (causes.length === 1) { - // Metrics and probability will already have been placed at the top level. - // If cause has byFieldValue, move it to a top level fields for display. - const cause = _.first(causes); - if (_.has(cause, 'by_field_name')) { - scope.singleCauseByFieldName = cause.by_field_name; - scope.singleCauseByFieldValue = cause.by_field_value; - } - } else { - scope.causes = _.map(causes, (cause) => { - const simplified = _.pick(cause, 'typical', 'actual', 'probability'); - // Get the 'entity field name/value' to display in the cause - - // For by and over, use by_field_name/Value (over_field_name/Value are in the toplevel fields) - // For just an 'over' field - the over_field_name/Value appear in both top level and cause. - simplified.entityName = _.has(cause, 'by_field_name') ? cause.by_field_name : cause.over_field_name; - simplified.entityValue = _.has(cause, 'by_field_value') ? cause.by_field_value : cause.over_field_value; - return simplified; - }); - } - - } - } - - function buildInfluencers() { - if (_.has(scope.record, 'influencers')) { - const recordInfluencers = scope.record.influencers; - scope.influencersNumToDislay = Math.min(scope.influencersNumToDislay, recordInfluencers.length); - let othersCount = Math.max(recordInfluencers.length - scope.influencersNumToDislay, 0); - - if (othersCount === 1) { - // Display the 1 extra influencer as displaying "and 1 more" would also take up a line. - scope.influencersNumToDislay++; - othersCount = 0; - } - - const influencers = []; - for (let i = 0; i < scope.influencersNumToDislay; i++) { - _.each(recordInfluencers[i], (influencerFieldValue, influencerFieldName) => { - influencers.push({ 'name': influencerFieldName, 'value': influencerFieldValue }); - }); - } - - scope.influencers = influencers; - scope.otherInfluencersCount = othersCount; - } - } - } - - - return { - restrict: 'AE', - replace: false, - scope: {}, - template, - link: link - }; -}); diff --git a/x-pack/plugins/ml/public/components/anomalies_table/index.js b/x-pack/plugins/ml/public/components/anomalies_table/index.js index 65271895fb3133..f9fb2bc0dafa09 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/index.js +++ b/x-pack/plugins/ml/public/components/anomalies_table/index.js @@ -5,7 +5,6 @@ */ - -import './styles/main.less'; -import './anomalies_table_directive.js'; +import './anomalies_table_directive'; import './anomalies_table_service.js'; +import './styles/main.less'; diff --git a/x-pack/plugins/ml/public/components/anomalies_table/influencers_cell/influencers_cell.js b/x-pack/plugins/ml/public/components/anomalies_table/influencers_cell.js similarity index 57% rename from x-pack/plugins/ml/public/components/anomalies_table/influencers_cell/influencers_cell.js rename to x-pack/plugins/ml/public/components/anomalies_table/influencers_cell.js index a712904b302985..78400b3fe7ebd2 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/influencers_cell/influencers_cell.js +++ b/x-pack/plugins/ml/public/components/anomalies_table/influencers_cell.js @@ -5,7 +5,6 @@ */ - import _ from 'lodash'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; @@ -21,23 +20,8 @@ export class InfluencersCell extends Component { constructor(props) { super(props); - this.limit = props.limit; - const recordInfluencers = props.influencers || []; - this.influencers = []; - _.each(recordInfluencers, (influencer) => { - _.each(influencer, (influencerFieldValue, influencerFieldName) => { - this.influencers.push({ - influencerFieldName, - influencerFieldValue - }); - }); - }); - - // Allow one more influencer than the supplied limit as displaying - // 'and 1 more' would take up an extra line. - const showAll = this.influencers.length <= (this.limit + 1); this.state = { - showAll + showAll: false }; } @@ -45,36 +29,42 @@ export class InfluencersCell extends Component { this.setState({ showAll: !this.state.showAll }); } - renderInfluencers() { - const numberToDisplay = this.state.showAll === false ? this.limit : this.influencers.length; - const displayInfluencers = this.influencers.slice(0, numberToDisplay); + renderInfluencers(influencers) { + const numberToDisplay = (this.state.showAll === false) ? this.props.limit : influencers.length; + const displayInfluencers = influencers.slice(0, numberToDisplay); - this.othersCount = Math.max(this.influencers.length - numberToDisplay, 0); - if (this.othersCount === 1) { + let othersCount = Math.max(influencers.length - numberToDisplay, 0); + if (othersCount === 1) { // Display the additional influencer. - displayInfluencers.push(this.influencers[this.limit]); - this.othersCount = 0; + displayInfluencers.push(influencers[this.props.limit]); + othersCount = 0; } - return displayInfluencers.map((influencer, index) => { - return ( -
{influencer.influencerFieldName}: {influencer.influencerFieldValue}
- ); - }); + const displayRows = displayInfluencers.map((influencer, index) => ( +
{influencer.influencerFieldName}: {influencer.influencerFieldValue}
+ )); + + + return ( + + {displayRows} + {this.renderOthers(influencers.length, othersCount)} + + ); } - renderOthers() { - if (this.othersCount > 0) { + renderOthers(totalCount, othersCount) { + if (othersCount > 0) { return (
this.toggleAllInfluencers()} > - and {this.othersCount} more + and {othersCount} more
); - } else if (this.influencers.length > this.limit + 1) { + } else if (totalCount > this.props.limit + 1) { return (
{ + _.each(influencer, (influencerFieldValue, influencerFieldName) => { + influencers.push({ + influencerFieldName, + influencerFieldValue + }); + }); + }); + return (
- {this.renderInfluencers()} - {this.renderOthers()} + {this.renderInfluencers(influencers)} + {this.renderOthers(influencers)}
); } diff --git a/x-pack/plugins/ml/public/components/anomalies_table/influencers_cell/influencers_cell_directive.js b/x-pack/plugins/ml/public/components/anomalies_table/influencers_cell/influencers_cell_directive.js deleted file mode 100644 index 09aa97c28f347d..00000000000000 --- a/x-pack/plugins/ml/public/components/anomalies_table/influencers_cell/influencers_cell_directive.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - - -import 'ngreact'; - -import { InfluencersCell } from './influencers_cell'; - -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml', ['react']); -module.directive('mlInfluencersCell', function (reactDirective) { - return reactDirective(InfluencersCell, undefined, { restrict: 'E' }); -}); diff --git a/x-pack/plugins/ml/public/components/anomalies_table/links_menu.js b/x-pack/plugins/ml/public/components/anomalies_table/links_menu.js new file mode 100644 index 00000000000000..d77716049237e3 --- /dev/null +++ b/x-pack/plugins/ml/public/components/anomalies_table/links_menu.js @@ -0,0 +1,414 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + +import _ from 'lodash'; +import moment from 'moment'; +import rison from 'rison-node'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; + +import { + EuiButtonEmpty, + EuiContextMenuPanel, + EuiContextMenuItem, + EuiPopover +} from '@elastic/eui'; + +import 'ui/timefilter'; +import chrome from 'ui/chrome'; +import { toastNotifications } from 'ui/notify'; + +import { ES_FIELD_TYPES } from 'plugins/ml/../common/constants/field_types'; +import { parseInterval } from 'plugins/ml/../common/util/parse_interval'; +import { getFieldTypeFromMapping } from 'plugins/ml/services/mapping_service'; +import { ml } from 'plugins/ml/services/ml_api_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; +import { getUrlForRecord } from 'plugins/ml/util/custom_url_utils'; +import { getIndexPatterns } from 'plugins/ml/util/index_utils'; +import { replaceStringTokens } from 'plugins/ml/util/string_utils'; + + +/* + * Component for rendering the links menu inside a cell in the anomalies table. + */ +export class LinksMenu extends Component { + constructor(props) { + super(props); + + this.state = { + isPopoverOpen: false, + toasts: [] + }; + } + + openCustomUrl = (customUrl) => { + const { anomaly, interval, isAggregatedData } = this.props; + + console.log('Anomalies Table - open customUrl for record:', anomaly); + + // If url_value contains $earliest$ and $latest$ tokens, add in times to the source record. + // Create a copy of the record as we are adding properties into it. + const record = _.cloneDeep(anomaly.source); + const timestamp = record.timestamp; + const configuredUrlValue = customUrl.url_value; + const timeRangeInterval = parseInterval(customUrl.time_range); + if (configuredUrlValue.includes('$earliest$')) { + let earliestMoment = moment(timestamp); + if (timeRangeInterval !== null) { + earliestMoment.subtract(timeRangeInterval); + } else { + earliestMoment = moment(timestamp).startOf(interval); + if (interval === 'hour') { + // Start from the previous hour. + earliestMoment.subtract(1, 'h'); + } + } + record.earliest = earliestMoment.toISOString(); // e.g. 2016-02-08T16:00:00.000Z + } + + if (configuredUrlValue.includes('$latest$')) { + let latestMoment = moment(timestamp).add(record.bucket_span, 's'); + if (timeRangeInterval !== null) { + latestMoment.add(timeRangeInterval); + } else { + if (isAggregatedData === true) { + latestMoment = moment(timestamp).endOf(interval); + if (interval === 'hour') { + // Show to the end of the next hour. + latestMoment.add(1, 'h'); // e.g. 2016-02-08T18:59:59.999Z + } + } + } + record.latest = latestMoment.toISOString(); + } + + // If url_value contains $mlcategoryterms$ or $mlcategoryregex$, add in the + // terms and regex for the selected categoryId to the source record. + if ((configuredUrlValue.includes('$mlcategoryterms$') || configuredUrlValue.includes('$mlcategoryregex$')) + && _.has(record, 'mlcategory')) { + const jobId = record.job_id; + + // mlcategory in the source record will be an array + // - use first value (will only ever be more than one if influenced by category other than by/partition/over). + const categoryId = record.mlcategory[0]; + + ml.results.getCategoryDefinition(jobId, categoryId) + .then((resp) => { + // Prefix each of the terms with '+' so that the Elasticsearch Query String query + // run in a drilldown Kibana dashboard has to match on all terms. + const termsArray = resp.terms.split(' ').map(term => `+${term}`); + record.mlcategoryterms = termsArray.join(' '); + record.mlcategoryregex = resp.regex; + + // Replace any tokens in the configured url_value with values from the source record, + // and then open link in a new tab/window. + const urlPath = replaceStringTokens(customUrl.url_value, record, true); + window.open(urlPath, '_blank'); + + }).catch((resp) => { + console.log('openCustomUrl(): error loading categoryDefinition:', resp); + toastNotifications.addDanger( + `Unable to open link as an error occurred loading details on category ID ${categoryId}`); + }); + + } else { + // Replace any tokens in the configured url_value with values from the source record, + // and then open link in a new tab/window. + const urlPath = getUrlForRecord(customUrl, record); + window.open(urlPath, '_blank'); + } + + }; + + viewSeries = () => { + const record = this.props.anomaly.source; + const bounds = this.props.timefilter.getActiveBounds(); + const from = bounds.min.toISOString(); // e.g. 2016-02-08T16:00:00.000Z + const to = bounds.max.toISOString(); + + // Zoom to show 50 buckets either side of the record. + const recordTime = moment(record.timestamp); + const zoomFrom = recordTime.subtract(50 * record.bucket_span, 's').toISOString(); + const zoomTo = recordTime.add(100 * record.bucket_span, 's').toISOString(); + + // Extract the by, over and partition fields for the record. + const entityCondition = {}; + + if (_.has(record, 'partition_field_value')) { + entityCondition[record.partition_field_name] = record.partition_field_value; + } + + if (_.has(record, 'over_field_value')) { + entityCondition[record.over_field_name] = record.over_field_value; + } + + if (_.has(record, 'by_field_value')) { + // Note that analyses with by and over fields, will have a top-level by_field_name, + // but the by_field_value(s) will be in the nested causes array. + // TODO - drilldown from cause in expanded row only? + entityCondition[record.by_field_name] = record.by_field_value; + } + + // Use rison to build the URL . + const _g = rison.encode({ + ml: { + jobIds: [record.job_id] + }, + refreshInterval: { + display: 'Off', + pause: false, + value: 0 + }, + time: { + from: from, + to: to, + mode: 'absolute' + } + }); + + const _a = rison.encode({ + mlTimeSeriesExplorer: { + zoom: { + from: zoomFrom, + to: zoomTo + }, + detectorIndex: record.detector_index, + entities: entityCondition, + }, + filters: [], + query: { + query_string: { + analyze_wildcard: true, + query: '*' + } + } + }); + + // Need to encode the _a parameter in case any entities contain unsafe characters such as '+'. + let path = `${chrome.getBasePath()}/app/ml#/timeseriesexplorer`; + path += `?_g=${_g}&_a=${encodeURIComponent(_a)}`; + window.open(path, '_blank'); + } + + viewExamples = () => { + const categoryId = this.props.anomaly.entityValue; + const record = this.props.anomaly.source; + const indexPatterns = getIndexPatterns(); + + const job = mlJobService.getJob(this.props.anomaly.jobId); + if (job === undefined) { + console.log(`viewExamples(): no job found with ID: ${this.props.anomaly.jobId}`); + toastNotifications.addDanger( + `Unable to view examples as no details could be found for job ID ${this.props.anomaly.jobId}`); + return; + } + const categorizationFieldName = job.analysis_config.categorization_field_name; + const datafeedIndices = job.datafeed_config.indices; + // Find the type of the categorization field i.e. text (preferred) or keyword. + // Uses the first matching field found in the list of indices in the datafeed_config. + // attempt to load the field type using each index. we have to do it this way as _field_caps + // doesn't specify which index a field came from unless there is a clash. + let i = 0; + findFieldType(datafeedIndices[i]); + + function findFieldType(index) { + getFieldTypeFromMapping(index, categorizationFieldName) + .then((resp) => { + if (resp !== '') { + createAndOpenUrl(index, resp); + } else { + i++; + if (i < datafeedIndices.length) { + findFieldType(datafeedIndices[i]); + } else { + error(); + } + } + }) + .catch(() => { + error(); + }); + } + + function createAndOpenUrl(index, categorizationFieldType) { + // Find the ID of the index pattern with a title attribute which matches the + // index configured in the datafeed. If a Kibana index pattern has not been created + // for this index, then the user will see a warning message on the Discover tab advising + // them that no matching index pattern has been configured. + let indexPatternId = index; + for (let j = 0; j < indexPatterns.length; j++) { + if (indexPatterns[j].get('title') === index) { + indexPatternId = indexPatterns[j].id; + break; + } + } + + // Get the definition of the category and use the terms or regex to view the + // matching events in the Kibana Discover tab depending on whether the + // categorization field is of mapping type text (preferred) or keyword. + ml.results.getCategoryDefinition(record.job_id, categoryId) + .then((resp) => { + let query = null; + // Build query using categorization regex (if keyword type) or terms (if text type). + // Check for terms or regex in case categoryId represents an anomaly from the absence of the + // categorization field in documents (usually indicated by a categoryId of -1). + if (categorizationFieldType === ES_FIELD_TYPES.KEYWORD) { + if (resp.regex) { + query = `${categorizationFieldName}:/${resp.regex}/`; + } + } else { + if (resp.terms) { + query = `${categorizationFieldName}:` + resp.terms.split(' ').join(` AND ${categorizationFieldName}:`); + } + } + + const recordTime = moment(record.timestamp); + const from = recordTime.toISOString(); + const to = recordTime.add(record.bucket_span, 's').toISOString(); + + // Use rison to build the URL . + const _g = rison.encode({ + refreshInterval: { + display: 'Off', + pause: false, + value: 0 + }, + time: { + from: from, + to: to, + mode: 'absolute' + } + }); + + const appStateProps = { + index: indexPatternId, + filters: [] + }; + if (query !== null) { + appStateProps.query = { + query_string: { + analyze_wildcard: true, + query: query + } + }; + } + const _a = rison.encode(appStateProps); + + // Need to encode the _a parameter as it will contain characters such as '+' if using the regex. + let path = chrome.getBasePath(); + path += '/app/kibana#/discover'; + path += '?_g=' + _g; + path += '&_a=' + encodeURIComponent(_a); + window.open(path, '_blank'); + + }).catch((resp) => { + console.log('viewExamples(): error loading categoryDefinition:', resp); + toastNotifications.addDanger( + `Unable to view examples as an error occurred loading details on category ID ${categoryId}`); + }); + + } + + function error() { + console.log(`viewExamples(): error finding type of field ${categorizationFieldName} in indices:`, + datafeedIndices); + toastNotifications.addDanger( + `Unable to view examples of documents with mlcategory ${categoryId} ` + + `as no mapping could be found for the categorization field ${categorizationFieldName}`); + } + }; + + onButtonClick = () => { + this.setState(prevState => ({ + isPopoverOpen: !prevState.isPopoverOpen, + })); + }; + + closePopover = () => { + this.setState({ + isPopoverOpen: false, + }); + }; + + render() { + const { anomaly, showViewSeriesLink } = this.props; + + const button = ( + + Open link + + ); + + const items = []; + if (anomaly.customUrls !== undefined) { + anomaly.customUrls.forEach((customUrl, index) => { + items.push( + { this.closePopover(); this.openCustomUrl(customUrl); }} + > + {customUrl.url_name} + + ); + }); + } + + if (showViewSeriesLink === true && anomaly.isTimeSeriesViewDetector === true) { + items.push( + { this.closePopover(); this.viewSeries(); }} + > + View series + + ); + } + + if (anomaly.entityName === 'mlcategory') { + items.push( + { this.closePopover(); this.viewExamples(); }} + > + View examples + + ); + } + + return ( + + + + ); + } +} + +LinksMenu.propTypes = { + anomaly: PropTypes.object.isRequired, + showViewSeriesLink: PropTypes.bool, + isAggregatedData: PropTypes.bool, + interval: PropTypes.string, + timefilter: PropTypes.object.isRequired +}; diff --git a/x-pack/plugins/ml/public/components/anomalies_table/styles/main.less b/x-pack/plugins/ml/public/components/anomalies_table/styles/main.less index 9527ce538d9233..a71d790ce538a9 100644 --- a/x-pack/plugins/ml/public/components/anomalies_table/styles/main.less +++ b/x-pack/plugins/ml/public/components/anomalies_table/styles/main.less @@ -1,126 +1,114 @@ -ml-anomalies-table { +.ml-anomalies-table { + .ml-icon-severity-critical, + .ml-icon-severity-major, + .ml-icon-severity-minor, + .ml-icon-severity-warning, + .ml-icon-severity-unknown { + color: inherit; + text-shadow: none; + } - .anomalies-table { - padding: 10px; + .ml-icon-severity-critical { + .euiIcon { + fill: #fe5050; + } + } - .no-results-item { - text-align: center; - padding-top: 10px; + .ml-icon-severity-major { + .euiIcon { + fill: #fba740; } + } - .table { - margin-bottom: 35px; + .ml-icon-severity-minor { + .euiIcon { + fill: #fdec25; + } + } - td, th { - color: #2d2d2d; - font-size: 12px; - white-space: nowrap; + .ml-icon-severity-warning { + .euiIcon { + fill: #8bc8fb; + } + } - .kuiButton.dropdown-toggle { - font-size: 12px; - } + .ml-icon-severity-unknown { + .euiIcon { + fill: #c0c0c0; + } + } - .fa.fa-arrow-up, .fa.fa-arrow-down { - font-size: 11px; - color: #686868; - } + tr th:first-child, + tr td:first-child { + width: 32px; + } - button { - border: none; - } - button:focus { - outline: none; - } - } + .euiTableCellContent { + .euiHealth { + font-size: inherit; + } - td { - button { - font-family: inherit; - background-color: transparent; - } - } + .filter-button { + opacity: 0.3; + width: 20px; + padding-top: 2px; - th { - button { - background-color: #FFFFFF; - padding: 0px 2px; - } + .euiIcon { + width: 14px; + height: 14px; } } - .agg-table-paginated { - overflow-x: auto; - .dropdown-menu { - left: -60px; - } + .filter-button:hover { + opacity: 1; } + } - .ml-anomaly-interim-result { - font-style:italic; - padding-bottom: 3px; - } + .euiContextMenuItem { + min-width: 150px + } - .ml-tablerow-expanded { - width: 100%; - padding: 5px 20px; - overflow: hidden; - font-size: 12px; - - table { - td { - padding: 0px 0px 2px 0px; - button { - padding: 0px 0px; - } - } + .category-example { + display: block; + white-space: nowrap; + } - tr>td:first-child { - padding-left: 2px; - vertical-align: top; - } + .interim-result { + font-style: italic; + } - td:first-child { - width: 140px; - } + .ml-anomalies-table-details { + padding: 4px 32px; + max-height: 1000px; + overflow-y: auto; - td:nth-child(2) { - padding-left: 5px; - } + .anomaly-description-list { + + .euiDescriptionList__title { + margin-top: 0px; + flex-basis: 15%; + font-size: inherit; } - } + .euiDescriptionList__description { + margin-top: 0px; + flex-basis: 85%; + font-size: inherit; + } - .ml-tablerow-expanded-heading { - font-weight: bold; - display: block; - padding-top: 5px; - } + .filter-button { + height: 20px; + padding-top: 2px; - .ml-tablerow-expanded-heading:first-child { - padding-top: 0px; - } + .euiButtonIcon__icon { + -webkit-transform: translateY(-7px); + transform: translateY(-7px); + } + } - .ml-tablerow-expanded-mv-description { - display: block; } - } -} -.ml-anomalies-table.dropdown-menu { - min-width: 120px; - font-size: 12px; } -.ml-anomalies-table.dropdown-menu > li > a { - color: #444444; - text-decoration: none; -} - -.ml-anomalies-table.dropdown-menu > li > a:hover, -.ml-anomalies-table.dropdown-menu > li > a:active, -.ml-anomalies-table.dropdown-menu > li > a:focus { - color: #ffffff; - box-shadow: none; -} diff --git a/x-pack/plugins/ml/public/components/chart_tooltip/__tests__/chart_tooltip.js b/x-pack/plugins/ml/public/components/chart_tooltip/__tests__/chart_tooltip.js new file mode 100644 index 00000000000000..5f5c1c465947c4 --- /dev/null +++ b/x-pack/plugins/ml/public/components/chart_tooltip/__tests__/chart_tooltip.js @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import ngMock from 'ng_mock'; +import expect from 'expect.js'; + +describe('ML - mlChartTooltipService', () => { + let mlChartTooltipService; + + beforeEach(ngMock.module('kibana')); + beforeEach(() => { + ngMock.inject(function ($injector) { + mlChartTooltipService = $injector.get('mlChartTooltipService'); + }); + }); + + it('service API duck typing', () => { + expect(mlChartTooltipService).to.be.an('object'); + expect(mlChartTooltipService.show).to.be.a('function'); + expect(mlChartTooltipService.hide).to.be.a('function'); + }); + +}); diff --git a/x-pack/plugins/ml/public/components/chart_tooltip/chart_tooltip.js b/x-pack/plugins/ml/public/components/chart_tooltip/chart_tooltip.js index 1a0a66fb4efb82..8f2861a0aad3cc 100644 --- a/x-pack/plugins/ml/public/components/chart_tooltip/chart_tooltip.js +++ b/x-pack/plugins/ml/public/components/chart_tooltip/chart_tooltip.js @@ -68,20 +68,20 @@ module.directive('mlChartTooltip', function (mlChartTooltipService) { 'display': 'block' }); } + }; - this.hide = function () { - if (this.element !== null) { - this.element.css({ - 'opacity': '0', - }); + this.hide = function () { + if (this.element !== null) { + this.element.css({ + 'opacity': '0', + }); - // after the fade out transition has finished, set the display to - // none so it doesn't block any mouse events underneath it. - this.fadeTimeout = $timeout(() => { - this.element.css('display', 'none'); - this.fadeTimeout = null; - }, FADE_TIMEOUT_MS); - } - }; + // after the fade out transition has finished, set the display to + // none so it doesn't block any mouse events underneath it. + this.fadeTimeout = $timeout(() => { + this.element.css('display', 'none'); + this.fadeTimeout = null; + }, FADE_TIMEOUT_MS); + } }; }); diff --git a/x-pack/plugins/ml/public/components/confirm_modal/confirm_modal_service.js b/x-pack/plugins/ml/public/components/confirm_modal/confirm_modal_service.js index a4dc6f6697642b..18ffa53c441fc6 100644 --- a/x-pack/plugins/ml/public/components/confirm_modal/confirm_modal_service.js +++ b/x-pack/plugins/ml/public/components/confirm_modal/confirm_modal_service.js @@ -13,10 +13,10 @@ import template from './confirm_modal.html'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); -module.service('mlConfirmModalService', function ($modal, $q) { +module.service('mlConfirmModalService', function ($modal) { this.open = function (options) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { $modal.open({ template, controller: 'MlConfirmModal', diff --git a/x-pack/plugins/ml/public/components/data_recognizer/data_recognizer.js b/x-pack/plugins/ml/public/components/data_recognizer/data_recognizer.js index 23e55862f34864..cc13feaa4a9cc3 100644 --- a/x-pack/plugins/ml/public/components/data_recognizer/data_recognizer.js +++ b/x-pack/plugins/ml/public/components/data_recognizer/data_recognizer.js @@ -13,59 +13,54 @@ import { RecognizedResult } from './recognized_result'; import { ml } from 'plugins/ml/services/ml_api_service'; -export function dataRecognizerProvider() { +export class DataRecognizer extends Component { + constructor(props) { + super(props); - class DataRecognizer extends Component { - constructor(props) { - super(props); + this.state = { + results: [] + }; - this.state = { - results: [] - }; - - this.indexPattern = props.indexPattern; - this.savedSearch = props.savedSearch; - this.className = props.className; - this.results = props.results; - } + this.indexPattern = props.indexPattern; + this.savedSearch = props.savedSearch; + this.className = props.className; + this.results = props.results; + } - componentDidMount() { - // once the mount is complete, call the recognize endpoint to see if the index format is known to us, - ml.recognizeIndex({ indexPatternTitle: this.indexPattern.title }) - .then((resp) => { - const results = resp.map((r) => ( - - )); - if (typeof this.results === 'object') { - this.results.count = results.length; - } + componentDidMount() { + // once the mount is complete, call the recognize endpoint to see if the index format is known to us, + ml.recognizeIndex({ indexPatternTitle: this.indexPattern.title }) + .then((resp) => { + const results = resp.map((r) => ( + + )); + if (typeof this.results === 'object') { + this.results.count = results.length; + } - this.setState({ - results - }); + this.setState({ + results }); - } - - render() { - return ( -
- {this.state.results} -
- ); - } + }); } - DataRecognizer.propTypes = { - indexPattern: PropTypes.object, - savedSearch: PropTypes.object, - className: PropTypes.string, - results: PropTypes.object, - }; - - return DataRecognizer; + render() { + return ( +
+ {this.state.results} +
+ ); + } } + +DataRecognizer.propTypes = { + indexPattern: PropTypes.object, + savedSearch: PropTypes.object, + className: PropTypes.string, + results: PropTypes.object, +}; diff --git a/x-pack/plugins/ml/public/components/data_recognizer/data_recognizer_directive.js b/x-pack/plugins/ml/public/components/data_recognizer/data_recognizer_directive.js index 4edea6330d0767..81186fb9af8128 100644 --- a/x-pack/plugins/ml/public/components/data_recognizer/data_recognizer_directive.js +++ b/x-pack/plugins/ml/public/components/data_recognizer/data_recognizer_directive.js @@ -8,11 +8,10 @@ import 'ngreact'; -import { dataRecognizerProvider } from './data_recognizer'; +import { DataRecognizer } from './data_recognizer'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml', ['react']); -module.directive('mlDataRecognizer', function (reactDirective, Private) { - const DataRecognizer = Private(dataRecognizerProvider); +module.directive('mlDataRecognizer', function (reactDirective) { return reactDirective(DataRecognizer, undefined, { restrict: 'AE' }); }); diff --git a/x-pack/plugins/ml/public/components/documentation_help_link/__snapshots__/documentation_help_link_view.test.js.snap b/x-pack/plugins/ml/public/components/documentation_help_link/__snapshots__/documentation_help_link_view.test.js.snap new file mode 100644 index 00000000000000..ff953f5a97ca0b --- /dev/null +++ b/x-pack/plugins/ml/public/components/documentation_help_link/__snapshots__/documentation_help_link_view.test.js.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DocumentationHelpLink renders the link 1`] = ` + + Label Text + + + +`; diff --git a/x-pack/plugins/ml/public/components/documentation_help_link/documentation_help_link.js b/x-pack/plugins/ml/public/components/documentation_help_link/documentation_help_link.js index 60ebff776d36ab..7faf675199879a 100644 --- a/x-pack/plugins/ml/public/components/documentation_help_link/documentation_help_link.js +++ b/x-pack/plugins/ml/public/components/documentation_help_link/documentation_help_link.js @@ -6,7 +6,8 @@ -// the tooltip descriptions are located in tooltips.json +import React from 'react'; +import ReactDOM from 'react-dom'; import './styles/main.less'; @@ -15,6 +16,8 @@ import { metadata } from 'ui/metadata'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); +import { DocumentationHelpLink } from './documentation_help_link_view'; + module.directive('mlDocumentationHelpLink', function () { return { scope: { @@ -23,17 +26,20 @@ module.directive('mlDocumentationHelpLink', function () { }, restrict: 'AE', replace: true, - template: '' + - '{{label}}', - controller: function ($scope) { + link: function (scope, element) { const baseUrl = 'https://www.elastic.co'; // metadata.branch corresponds to the version used in documentation links. const version = metadata.branch; - $scope.fullUrl = function () { - return `${baseUrl}/guide/en/x-pack/${version}/${$scope.uri}`; + const props = { + fullUrl: `${baseUrl}/guide/en/x-pack/${version}/${scope.uri}`, + label: scope.label }; + + ReactDOM.render( + React.createElement(DocumentationHelpLink, props), + element[0] + ); } }; diff --git a/x-pack/plugins/ml/public/components/documentation_help_link/documentation_help_link_view.js b/x-pack/plugins/ml/public/components/documentation_help_link/documentation_help_link_view.js new file mode 100644 index 00000000000000..bd86b7f6b8e365 --- /dev/null +++ b/x-pack/plugins/ml/public/components/documentation_help_link/documentation_help_link_view.js @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import PropTypes from 'prop-types'; +import React from 'react'; +import { EuiIcon } from '@elastic/eui'; + +export function DocumentationHelpLink({ fullUrl, label }) { + return ( + + {label} + + ); +} +DocumentationHelpLink.propTypes = { + fullUrl: PropTypes.string.isRequired, + label: PropTypes.string.isRequired +}; diff --git a/x-pack/plugins/ml/public/components/documentation_help_link/documentation_help_link_view.test.js b/x-pack/plugins/ml/public/components/documentation_help_link/documentation_help_link_view.test.js new file mode 100644 index 00000000000000..0a9f2ab165f6b8 --- /dev/null +++ b/x-pack/plugins/ml/public/components/documentation_help_link/documentation_help_link_view.test.js @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { shallow } from 'enzyme'; +import React from 'react'; + +import { DocumentationHelpLink } from './documentation_help_link_view'; + +describe('DocumentationHelpLink', () => { + const props = { + fullUrl: 'http://fullUrl', + label: 'Label Text' + }; + + const component = ( + + ); + + const wrapper = shallow(component); + + test('renders the link', () => { + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/ml/public/components/field_data_card/field_data_card.html b/x-pack/plugins/ml/public/components/field_data_card/field_data_card.html index 34c55763ad6e0e..399a29fd001707 100644 --- a/x-pack/plugins/ml/public/components/field_data_card/field_data_card.html +++ b/x-pack/plugins/ml/public/components/field_data_card/field_data_card.html @@ -1,11 +1,9 @@
- + type="card.type" + tooltip-enabled="true" + />
+`; + +exports[`FieldTypeIcon update component 1`] = ` + +`; diff --git a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon.html b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon.html deleted file mode 100644 index d60055c38d67e3..00000000000000 --- a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_directive.js b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_directive.js index 024c751b0e72e3..4fef02f0c8bfd2 100644 --- a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_directive.js +++ b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_directive.js @@ -6,8 +6,10 @@ -import template from './field_type_icon.html'; -import { ML_JOB_FIELD_TYPES } from 'plugins/ml/../common/constants/field_types'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +import { FieldTypeIcon } from './field_type_icon_view.js'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); @@ -15,13 +17,27 @@ const module = uiModules.get('apps/ml'); module.directive('mlFieldTypeIcon', function () { return { restrict: 'E', - replace: true, + replace: false, scope: { + tooltipEnabled: '=', type: '=' }, - template, - controller: function ($scope) { - $scope.ML_JOB_FIELD_TYPES = ML_JOB_FIELD_TYPES; + link: function (scope, element) { + scope.$watch('type', updateComponent); + + updateComponent(); + + function updateComponent() { + const props = { + tooltipEnabled: scope.tooltipEnabled, + type: scope.type + }; + + ReactDOM.render( + React.createElement(FieldTypeIcon, props), + element[0] + ); + } } }; }); diff --git a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.js b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.js new file mode 100644 index 00000000000000..33c2fda04edad0 --- /dev/null +++ b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.js @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import PropTypes from 'prop-types'; +import React from 'react'; + +import { EuiToolTip } from '@elastic/eui'; + +// don't use something like plugins/ml/../common +// because it won't work with the jest tests +import { ML_JOB_FIELD_TYPES } from '../../../common/constants/field_types'; + +export function FieldTypeIcon({ tooltipEnabled = false, type }) { + let ariaLabel = ''; + let iconClass = ''; + let iconChar = ''; + + switch (type) { + case ML_JOB_FIELD_TYPES.BOOLEAN: + ariaLabel = 'Boolean field'; + iconClass = 'fa-adjust'; + break; + case ML_JOB_FIELD_TYPES.DATE: + ariaLabel = 'Date field'; + iconClass = 'fa-clock-o'; + break; + case ML_JOB_FIELD_TYPES.NUMBER: + ariaLabel = 'Metric field'; + iconChar = '#'; + break; + case ML_JOB_FIELD_TYPES.GEO_POINT: + ariaLabel = 'Geo-point field'; + iconClass = 'fa-globe'; + break; + case ML_JOB_FIELD_TYPES.KEYWORD: + ariaLabel = 'Aggregatable string field'; + iconChar = 't'; + break; + case ML_JOB_FIELD_TYPES.TEXT: + ariaLabel = 'String field'; + iconClass = 'fa-file-text-o'; + break; + case ML_JOB_FIELD_TYPES.IP: + ariaLabel = 'IP address field'; + iconClass = 'fa-laptop'; + break; + default: + // if type doesn't match one of ML_JOB_FIELD_TYPES + // don't render the component at all + return null; + } + + let className = 'field-type-icon'; + if (iconClass !== '') { + className += ' kuiIcon ' + iconClass; + } + + const containerProps = { + ariaLabel, + className, + iconChar + }; + + if (tooltipEnabled === true) { + // wrap the inner component inside because EuiToolTip doesn't seem + // to support having another component directly inside the tooltip anchor + // see https://github.com/elastic/eui/issues/839 + return ( + + + + ); + } + + return ; +} +FieldTypeIcon.propTypes = { + tooltipEnabled: PropTypes.bool, + type: PropTypes.string +}; + +// If the tooltip is used, it will apply its events to its first inner child. +// To pass on its properties we apply `rest` to the outer `span` element. +function FieldTypeIconContainer({ ariaLabel, className, iconChar, ...rest }) { + return ( + + {(iconChar === '') ? ( + + ) : ( + + + + )} + + ); +} diff --git a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.test.js b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.test.js new file mode 100644 index 00000000000000..027b667fc2e2e2 --- /dev/null +++ b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.test.js @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { mount, shallow } from 'enzyme'; +import React from 'react'; + +import { FieldTypeIcon } from './field_type_icon_view'; + +describe('FieldTypeIcon', () => { + + test(`don't render component when type is undefined`, () => { + const wrapper = shallow(); + expect(wrapper.isEmptyRender()).toBeTruthy(); + }); + + test(`don't render component when type doesn't match a field type`, () => { + const wrapper = shallow(); + expect(wrapper.isEmptyRender()).toBeTruthy(); + }); + + test(`render component when type matches a field type`, () => { + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); + }); + + test(`render with tooltip and test hovering`, () => { + const wrapper = mount(); + const container = wrapper.find({ className: 'field-type-icon-container' }); + + expect(wrapper.find('EuiToolTip').children()).toHaveLength(1); + + container.simulate('mouseover'); + expect(wrapper.find('EuiToolTip').children()).toHaveLength(2); + + container.simulate('mouseout'); + expect(wrapper.find('EuiToolTip').children()).toHaveLength(1); + }); + + test(`update component`, () => { + const wrapper = shallow(); + expect(wrapper.isEmptyRender()).toBeTruthy(); + wrapper.setProps({ type: 'keyword' }); + expect(wrapper).toMatchSnapshot(); + }); + +}); diff --git a/x-pack/plugins/ml/public/components/form_label/form_label.js b/x-pack/plugins/ml/public/components/form_label/form_label.js index 5b145f7d3c0ede..0afba683c27f0d 100644 --- a/x-pack/plugins/ml/public/components/form_label/form_label.js +++ b/x-pack/plugins/ml/public/components/form_label/form_label.js @@ -31,7 +31,7 @@ module.directive('mlFormLabel', function () { transclude: true, template: ` - + ` }; }); diff --git a/x-pack/plugins/ml/public/components/form_label/styles/main.less b/x-pack/plugins/ml/public/components/form_label/styles/main.less index c03327fb3738f7..4965ef14d18b2a 100644 --- a/x-pack/plugins/ml/public/components/form_label/styles/main.less +++ b/x-pack/plugins/ml/public/components/form_label/styles/main.less @@ -1,11 +1,11 @@ ml-form-label { display: inline-flex; - i[ml-info-icon] { + span[ml-info-icon] { margin-top: 0px; } - i[ml-info-icon], + span[ml-info-icon], label { display: block; } diff --git a/x-pack/plugins/ml/public/components/full_time_range_selector/full_time_range_selector_service.js b/x-pack/plugins/ml/public/components/full_time_range_selector/full_time_range_selector_service.js index 483beb21d1fe9f..3f512c5e9049d2 100644 --- a/x-pack/plugins/ml/public/components/full_time_range_selector/full_time_range_selector_service.js +++ b/x-pack/plugins/ml/public/components/full_time_range_selector/full_time_range_selector_service.js @@ -11,16 +11,16 @@ import moment from 'moment'; import { ml } from 'plugins/ml/services/ml_api_service'; -export function FullTimeRangeSelectorServiceProvider(timefilter, Notifier, $q) { +export function FullTimeRangeSelectorServiceProvider(timefilter, Notifier) { const notify = new Notifier(); function setFullTimeRange(indexPattern, query) { // load the earliest and latest time stamps for the index - $q.when(ml.getTimeFieldRange({ + ml.getTimeFieldRange({ index: indexPattern.title, timeFieldName: indexPattern.timeFieldName, query - })) + }) .then((resp) => { timefilter.time.from = moment(resp.start.epoch).toISOString(); timefilter.time.to = moment(resp.end.epoch).toISOString(); diff --git a/x-pack/plugins/ml/public/components/influencers_list/index.js b/x-pack/plugins/ml/public/components/influencers_list/index.js index 43aca379549976..ab50fbb57f37a7 100644 --- a/x-pack/plugins/ml/public/components/influencers_list/index.js +++ b/x-pack/plugins/ml/public/components/influencers_list/index.js @@ -5,7 +5,5 @@ */ - - import './influencers_list_directive'; import './styles/main.less'; diff --git a/x-pack/plugins/ml/public/components/influencers_list/influencers_list.html b/x-pack/plugins/ml/public/components/influencers_list/influencers_list.html deleted file mode 100644 index 7f64cc3b3dad54..00000000000000 --- a/x-pack/plugins/ml/public/components/influencers_list/influencers_list.html +++ /dev/null @@ -1,51 +0,0 @@ -
- -
-
-
-

No influencers found

-
-
-
- -
- - - -
- -
-
{{influencer.influencerFieldValue}}
-
mlcategory {{influencer.influencerFieldValue}}
- - -
- -
-
-
-
-
- {{influencer.maxScoreLabel}} - -
- -
- {{influencer.totalScore | abbreviateWholeNumber:4}} -
-
- < 1 -
- -
- -
- -
- diff --git a/x-pack/plugins/ml/public/components/influencers_list/influencers_list.js b/x-pack/plugins/ml/public/components/influencers_list/influencers_list.js new file mode 100644 index 00000000000000..eedac15ef04424 --- /dev/null +++ b/x-pack/plugins/ml/public/components/influencers_list/influencers_list.js @@ -0,0 +1,150 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + +/* + * React component for rendering a list of Machine Learning influencers. + */ + +import PropTypes from 'prop-types'; +import React from 'react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, + EuiTitle, + EuiToolTip +} from '@elastic/eui'; + +import { abbreviateWholeNumber } from 'plugins/ml/formatters/abbreviate_whole_number'; +import { getSeverity } from 'plugins/ml/../common/util/anomaly_utils'; + + +function getTooltipContent(maxScoreLabel, totalScoreLabel) { + return ( + +

Maximum anomaly score: {maxScoreLabel}

+

Total anomaly score: {totalScoreLabel}

+
+ ); +} + +function Influencer({ influencerFieldName, valueData }) { + const maxScorePrecise = valueData.maxAnomalyScore; + const maxScore = parseInt(maxScorePrecise); + const maxScoreLabel = (maxScore !== 0) ? maxScore : '< 1'; + const severity = getSeverity(maxScore); + const totalScore = parseInt(valueData.sumAnomalyScore); + const totalScoreLabel = (totalScore !== 0) ? totalScore : '< 1'; + + // Ensure the bar has some width for 0 scores. + const barScore = (maxScore !== 0) ? maxScore : 1; + const barStyle = { + width: `${barScore}%` + }; + + const tooltipContent = getTooltipContent(maxScoreLabel, totalScoreLabel); + + return ( +
+
+ {(influencerFieldName !== 'mlcategory') ? ( +
{valueData.influencerFieldValue}
+ ) : ( +
mlcategory {valueData.influencerFieldValue}
+ )} +
+
+
+
+
+
+ + {maxScoreLabel} + +
+
+
+ + {(totalScore > 0) ? abbreviateWholeNumber(totalScore, 4) : totalScoreLabel} + +
+
+ ); +} +Influencer.propTypes = { + influencerFieldName: PropTypes.string.isRequired, + valueData: PropTypes.object.isRequired +}; + +function InfluencersByName({ influencerFieldName, fieldValues }) { + const influencerValues = fieldValues.map(valueData => ( + + )); + + return ( + + +

{influencerFieldName}

+
+ + {influencerValues} +
+ ); +} +InfluencersByName.propTypes = { + influencerFieldName: PropTypes.string.isRequired, + fieldValues: PropTypes.array.isRequired +}; + +export function InfluencersList({ influencers }) { + + if (influencers === undefined || Object.keys(influencers).length === 0) { + return ( + + + + +

No influencers found

+
+
+
+ ); + } + + const influencersByName = Object.keys(influencers).map(influencerFieldName => ( + + )); + + return ( +
+ {influencersByName} +
+ ); +} +InfluencersList.propTypes = { + influencers: PropTypes.object +}; diff --git a/x-pack/plugins/ml/public/components/influencers_list/influencers_list_directive.js b/x-pack/plugins/ml/public/components/influencers_list/influencers_list_directive.js index 574c56be510ceb..114620b49ab336 100644 --- a/x-pack/plugins/ml/public/components/influencers_list/influencers_list_directive.js +++ b/x-pack/plugins/ml/public/components/influencers_list/influencers_list_directive.js @@ -5,113 +5,19 @@ */ - -/* - * AngularJS directive for rendering a list of Machine Learning influencers. - */ - -import _ from 'lodash'; - -import 'plugins/ml/lib/angular_bootstrap_patch'; -import 'plugins/ml/filters/abbreviate_whole_number'; - -import template from './influencers_list.html'; -import { getSeverity } from 'plugins/ml/util/anomaly_utils'; -import { mlEscape } from 'plugins/ml/util/string_utils'; - -import { FilterManagerProvider } from 'ui/filter_manager'; +import 'ngreact'; import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - -module.directive('mlInfluencersList', function (Private) { - - const filterManager = Private(FilterManagerProvider); - - function link(scope, element) { - - scope.$on('render', function () { - render(); - }); - - element.on('$destroy', function () { - scope.$destroy(); - }); - - scope.tooltipPlacement = scope.tooltipPlacement === undefined ? 'top' : scope.tooltipPlacement; - - function render() { - if (scope.influencersData === undefined) { - return; - } - - const dataByViewBy = {}; - - // TODO - position tooltip so it doesn't go off edge of window. - const compiledTooltip = _.template( - '
<%= influencerFieldName %>: <%= influencerFieldValue %>' + - '
Max anomaly score: <%= maxScoreLabel %>' + - '
Total anomaly score: <%= totalScoreLabel %>
'); - - _.each(scope.influencersData, (fieldValues, influencerFieldName) => { - const valuesForViewBy = []; - - _.each(fieldValues, function (valueData) { - const influencerFieldValue = valueData.influencerFieldValue; - const maxScorePrecise = valueData.maxAnomalyScore; - const maxScore = parseInt(maxScorePrecise); - const totalScore = parseInt(valueData.sumAnomalyScore); - const barScore = maxScore !== 0 ? maxScore : 1; - const maxScoreLabel = maxScore !== 0 ? maxScore : '< 1'; - const totalScoreLabel = totalScore !== 0 ? totalScore : '< 1'; - const severity = getSeverity(maxScore); - - // Store the data for each influencerfieldname in an array to ensure - // reliable sorting by max score. - // If it was sorted as an object, the order when rendered using the AngularJS - // ngRepeat directive could not be relied upon to be the same as they were - // returned in the ES aggregation e.g. for numeric keys from a mlcategory influencer. - valuesForViewBy.push({ - influencerFieldValue, - maxScorePrecise, - barScore, - maxScoreLabel, - totalScore, - severity, - tooltip: compiledTooltip({ - influencerFieldName: mlEscape(influencerFieldName), - influencerFieldValue: mlEscape(influencerFieldValue), - maxScoreLabel, - totalScoreLabel - }) - }); - }); - - - dataByViewBy[influencerFieldName] = _.sortBy(valuesForViewBy, 'maxScorePrecise').reverse(); - }); - - scope.influencers = dataByViewBy; - } - - // Provide a filter function so filters can be added. - scope.filter = function (field, value, operator) { - filterManager.add(field, value, operator, scope.indexPatternId); - }; +const module = uiModules.get('apps/ml', ['react']); - scope.showNoResultsMessage = function () { - return (scope.influencersData === undefined) || (_.keys(scope.influencersData).length === 0); - }; +import { InfluencersList } from './influencers_list'; - } +module.directive('mlInfluencersList', function ($injector) { + const reactDirective = $injector.get('reactDirective'); - return { - scope: { - influencersData: '=', - indexPatternId: '=', - tooltipPlacement: '@' - }, - template, - link: link - }; + return reactDirective( + InfluencersList, + undefined, + { restrict: 'E' } + ); }); diff --git a/x-pack/plugins/ml/public/components/influencers_list/styles/main.less b/x-pack/plugins/ml/public/components/influencers_list/styles/main.less index ba36498b065b04..d1fd0f14ebb9ba 100644 --- a/x-pack/plugins/ml/public/components/influencers_list/styles/main.less +++ b/x-pack/plugins/ml/public/components/influencers_list/styles/main.less @@ -1,59 +1,26 @@ .ml-influencers-list { - width: 100%; - padding: 0px 0px; line-height: 1.45; - .visualize-error { - display: inline; - - h4 { - font-size: 16px; - margin-top: 65px; - } - } - - .section-label { - background-color: #9c9fa6; - color: #ffffff; - font-size:13px; - /* eui h3 equivalent font-weight */ - font-weight: 500; - margin-bottom: 5px; - padding: 2px 5px; - } - - .influencer-content { - padding-right: 4px; - padding-left: 4px; - } - .field-label { font-size: 12px; - padding-left: 2px; text-align: left; - .influencerfieldvalue { - max-width: calc(~"100% - 40px"); + .field-value { + max-width: calc(~"100% - 34px"); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; display: inline-block; vertical-align: bottom; } - - .filter-buttons { - padding-left: 5px; - display: inline-block; - vertical-align: bottom; - } } .progress { display:inline-block; - width: calc(~"100% - 40px"); - height: 20px; + width: calc(~"100% - 34px"); + height: 22px; min-width: 70px; - margin-bottom: 2px; + margin-bottom: 0px; color: #555; background-color : transparent; @@ -62,63 +29,76 @@ } .progress-bar { - height: 6px; - margin: 6px 0px; + height: 2px; + margin-top: 8px; text-align: right; line-height: 18px; - border-radius: 5px; display: inline-block; - + transition: none; } + } - .progress-bar.critical { + .progress.critical { + .progress-bar { background-color: #fe5050; } + .score-label { + border-color: #fe5050; + } + } - .progress-bar.major { + .progress.major { + .progress-bar { background-color: #fba740; } + .score-label { + border-color: #fba740; + } + } - .progress-bar.minor { + .progress.minor { + .progress-bar { background-color: #ffdd00; } + .score-label { + border-color: #ffdd00; + } + } - .progress-bar.warning { + .progress.warning { + .progress-bar { background-color: #8bc8fb; } - + .score-label { + border-color: #8bc8fb; + } } .score-label { - margin-left: 3px; text-align: center; - color: #444444; - padding: 2px 2px 2px 2px; - border-radius: 4px; line-height: 14px; white-space: nowrap; font-size: 12px; - display: inline-block; + display: inline; + margin-left: 4px; } - .score-label.total-score-label { + .total-score-label { width: 32px; vertical-align: top; - background-color: #444444; - color: white; + text-align: center; + color: #555; font-size: 11px; + line-height: 14px; + border-radius: 4px; + padding: 2px; + margin-top: 1px; + display: inline-block; + border: 1px solid #bbbbbb; } } .ml-influencers-list-tooltip { - color: #ffffff; - font-family: Roboto, Droid, Helvetica Neue, Helvetica, Arial, sans-serif; - font-size: 12px; - text-align: left; - - hr { - margin-top: 3px; - margin-bottom: 3px; - border-color: #95a5a6; - } + word-break: break-all; } + diff --git a/x-pack/plugins/ml/public/components/job_group_select/job_group_select.js b/x-pack/plugins/ml/public/components/job_group_select/job_group_select.js index 2b2a9055130653..1b413476e83abe 100644 --- a/x-pack/plugins/ml/public/components/job_group_select/job_group_select.js +++ b/x-pack/plugins/ml/public/components/job_group_select/job_group_select.js @@ -10,13 +10,13 @@ import _ from 'lodash'; import template from './job_group_select.html'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; -import { CalendarServiceProvider } from 'plugins/ml/services/calendar_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; +import { mlCalendarService } from 'plugins/ml/services/calendar_service'; import { InitAfterBindingsWorkaround } from 'ui/compat'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); -module.directive('mlJobGroupSelect', function (es, $timeout, Private) { +module.directive('mlJobGroupSelect', function () { return { restrict: 'E', template, @@ -30,8 +30,6 @@ module.directive('mlJobGroupSelect', function (es, $timeout, Private) { controller: class MlGroupSelectController extends InitAfterBindingsWorkaround { initAfterBindings($scope) { - const mlJobService = Private(JobServiceProvider); - const mlCalendarService = Private(CalendarServiceProvider); this.$scope = $scope; this.selectedGroups = []; this.groups = []; diff --git a/x-pack/plugins/ml/public/components/job_select_list/job_select_list_directive.js b/x-pack/plugins/ml/public/components/job_select_list/job_select_list_directive.js index edaf73b61eefe1..baf611b87e5d83 100644 --- a/x-pack/plugins/ml/public/components/job_select_list/job_select_list_directive.js +++ b/x-pack/plugins/ml/public/components/job_select_list/job_select_list_directive.js @@ -18,7 +18,7 @@ import d3 from 'd3'; import template from './job_select_list.html'; import { isTimeSeriesViewJob } from 'plugins/ml/../common/util/job_utils'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { JobSelectServiceProvider } from 'plugins/ml/components/job_select_list/job_select_service'; import { uiModules } from 'ui/modules'; @@ -31,7 +31,6 @@ module.directive('mlJobSelectList', function (Private, timefilter) { transclude: true, template, controller: function ($scope) { - const mlJobService = Private(JobServiceProvider); const mlJobSelectService = Private(JobSelectServiceProvider); $scope.jobs = []; $scope.groups = []; diff --git a/x-pack/plugins/ml/public/components/job_select_list/job_select_service.js b/x-pack/plugins/ml/public/components/job_select_list/job_select_service.js index 4e1b0d99c12c2c..cda64fe84ed135 100644 --- a/x-pack/plugins/ml/public/components/job_select_list/job_select_service.js +++ b/x-pack/plugins/ml/public/components/job_select_list/job_select_service.js @@ -11,12 +11,11 @@ import _ from 'lodash'; import { notify } from 'ui/notify'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; let jobSelectService = undefined; -export function JobSelectServiceProvider($rootScope, Private, globalState) { - const mlJobService = Private(JobServiceProvider); +export function JobSelectServiceProvider($rootScope, globalState) { function checkGlobalState() { if (globalState.ml === undefined) { diff --git a/x-pack/plugins/ml/public/components/json_tooltip/__tests__/json_tooltip.js b/x-pack/plugins/ml/public/components/json_tooltip/__tests__/json_tooltip.js index 20bb0568143366..49b1194616fbe7 100644 --- a/x-pack/plugins/ml/public/components/json_tooltip/__tests__/json_tooltip.js +++ b/x-pack/plugins/ml/public/components/json_tooltip/__tests__/json_tooltip.js @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ - - import ngMock from 'ng_mock'; import expect from 'expect.js'; @@ -46,6 +44,7 @@ describe('ML - ', () => { expect(scope.id).to.be(id); expect(scope.text).to.be(''); }); + it('Initialize with existing tooltip attribute', () => { const id = 'new_job_id'; $element = $compile(``)($scope); @@ -57,7 +56,7 @@ describe('ML - ', () => { expect(scope.text).to.be(tooltips[id].text); // test the rendered span element which should be referenced by aria-describedby - const span = $element.find('span'); + const span = $element.find('span.ml-info-tooltip-text'); expect(span[0].id).to.be('ml_aria_description_' + id); expect(span.text()).to.be(tooltips[id].text); }); diff --git a/x-pack/plugins/ml/public/components/json_tooltip/json_tooltip.js b/x-pack/plugins/ml/public/components/json_tooltip/json_tooltip.js index 3df2cdaee64b94..019a11f6462fc3 100644 --- a/x-pack/plugins/ml/public/components/json_tooltip/json_tooltip.js +++ b/x-pack/plugins/ml/public/components/json_tooltip/json_tooltip.js @@ -24,26 +24,33 @@ module.service('mlJsonTooltipService', function () { return ''; } }; -}) +}); // directive for placing an i icon with a popover tooltip anywhere on a page -// tooltip format: +// tooltip format: // the_id will match an entry in tooltips.json - .directive('mlInfoIcon', function () { - return { - scope: { - id: '@mlInfoIcon' - }, - restrict: 'AE', - replace: true, - template: ` - +// the original will be replaced with +// ... to transform the DOM structure +// into one which is suitable for use with EuiTooltip. Because of this replacement +// span[ml-info-icon] has to be used instead of i[ml-info-icon] when using CSS. +module.directive('mlInfoIcon', function () { + return { + scope: { + id: '@mlInfoIcon', + position: '@' + }, + restrict: 'AE', + replace: true, + template: ` + + + `, - controller: function ($scope) { - $scope.text = (tooltips[$scope.id]) ? tooltips[$scope.id].text : ''; - } - }; + controller: function ($scope) { + $scope.text = (tooltips[$scope.id]) ? tooltips[$scope.id].text : ''; + } + }; - }); +}); diff --git a/x-pack/plugins/ml/public/components/json_tooltip/styles/main.less b/x-pack/plugins/ml/public/components/json_tooltip/styles/main.less index 403faa2072e85e..d33956ce3b7991 100644 --- a/x-pack/plugins/ml/public/components/json_tooltip/styles/main.less +++ b/x-pack/plugins/ml/public/components/json_tooltip/styles/main.less @@ -1,4 +1,4 @@ -i[ml-info-icon] { +span[ml-info-icon] { color: #888; margin: 3px 4px; transition: color 0.15s; @@ -8,7 +8,7 @@ i[ml-info-icon] { } } -i[ml-info-icon]:hover { +span[ml-info-icon]:hover { color: #444; transition: color 0.15s 0.15s; } diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/index_listing/index.js b/x-pack/plugins/ml/public/components/tooltip/index.js similarity index 76% rename from x-pack/plugins/monitoring/public/components/elasticsearch/index_listing/index.js rename to x-pack/plugins/ml/public/components/tooltip/index.js index 31f94875772cc5..b789a3ec28bffe 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/index_listing/index.js +++ b/x-pack/plugins/ml/public/components/tooltip/index.js @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { ShowSytemIndicesCheckbox } from './show_system_indices_checkbox'; +import './tooltip_directive'; diff --git a/x-pack/plugins/ml/public/components/tooltip/tooltip_directive.js b/x-pack/plugins/ml/public/components/tooltip/tooltip_directive.js new file mode 100644 index 00000000000000..bd5a7d43f7e6fd --- /dev/null +++ b/x-pack/plugins/ml/public/components/tooltip/tooltip_directive.js @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; + +import { uiModules } from 'ui/modules'; +const module = uiModules.get('apps/ml', ['react']); + +import { Tooltip } from './tooltip_view'; + +module.directive('mlTooltip', function ($compile) { + const link = function (scope, element) { + const content = element.html(); + element.html(''); + + const props = { + position: scope.position, + text: scope.text, + transclude: (el) => { + const transcludeScope = scope.$new(); + const compiled = $compile(content)(transcludeScope); + el.append(compiled[0]); + } + }; + + ReactDOM.render( + React.createElement(Tooltip, props), + element[0] + ); + }; + + return { + restrict: 'A', + replace: true, + scope: false, + transclude: false, + link + }; +}); diff --git a/x-pack/plugins/ml/public/components/tooltip/tooltip_view.js b/x-pack/plugins/ml/public/components/tooltip/tooltip_view.js new file mode 100644 index 00000000000000..d2ebd4355a2557 --- /dev/null +++ b/x-pack/plugins/ml/public/components/tooltip/tooltip_view.js @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import PropTypes from 'prop-types'; + +import React from 'react'; + +import { + EuiToolTip +} from '@elastic/eui'; + +export function Tooltip({ position = 'top', text, transclude }) { + return ( + + + + ); +} +Tooltip.propTypes = { + position: PropTypes.string, + text: PropTypes.string, + transclude: PropTypes.func +}; diff --git a/x-pack/plugins/ml/public/components/validate_job/validate_job_directive.js b/x-pack/plugins/ml/public/components/validate_job/validate_job_directive.js index 9dff7938b9d77e..eb9184fb9db042 100644 --- a/x-pack/plugins/ml/public/components/validate_job/validate_job_directive.js +++ b/x-pack/plugins/ml/public/components/validate_job/validate_job_directive.js @@ -9,17 +9,13 @@ import 'ngreact'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml', ['react']); import { ValidateJob } from './validate_job_view'; +import { mlJobService } from 'plugins/ml/services/job_service'; -module.directive('mlValidateJob', function ($injector) { - const Private = $injector.get('Private'); - const mlJobService = Private(JobServiceProvider); - const reactDirective = $injector.get('reactDirective'); - +module.directive('mlValidateJob', function (reactDirective) { return reactDirective( ValidateJob, undefined, diff --git a/x-pack/plugins/ml/public/components/validate_job/validate_job_view.test.js b/x-pack/plugins/ml/public/components/validate_job/validate_job_view.test.js index a82a79d4dd2bc1..024dbb3dadf8d5 100644 --- a/x-pack/plugins/ml/public/components/validate_job/validate_job_view.test.js +++ b/x-pack/plugins/ml/public/components/validate_job/validate_job_view.test.js @@ -9,8 +9,6 @@ import React from 'react'; import { ValidateJob } from './validate_job_view'; -jest.mock('ui/chrome', () => { }, { virtual: true }); - const job = { job_id: 'test-id' }; diff --git a/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js b/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js index 305aabd8b7b0e8..7790d716a95ebf 100644 --- a/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js +++ b/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js @@ -30,9 +30,10 @@ import { IntervalHelperProvider } from 'plugins/ml/util/ml_time_buckets'; import { checkLicenseExpired } from 'plugins/ml/license/check_license'; import { checkGetJobsPrivilege } from 'plugins/ml/privilege/check_privilege'; import { createSearchItems } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; -import { getIndexPatternWithRoute, getSavedSearchWithRoute, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; +import { loadCurrentIndexPattern, loadCurrentSavedSearch, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; import { ml } from 'plugins/ml/services/ml_api_service'; +import { initPromise } from 'plugins/ml/util/promise'; import template from './datavisualizer.html'; uiRoutes @@ -41,9 +42,10 @@ uiRoutes resolve: { CheckLicense: checkLicenseExpired, privileges: checkGetJobsPrivilege, - indexPattern: getIndexPatternWithRoute, - savedSearch: getSavedSearchWithRoute, - checkMlNodesAvailable + indexPattern: loadCurrentIndexPattern, + savedSearch: loadCurrentSavedSearch, + checkMlNodesAvailable, + initPromise: initPromise(true) } }); @@ -56,7 +58,6 @@ module $route, $timeout, $window, - $q, Private, timefilter, AppState) { @@ -461,7 +462,7 @@ module buckets.setBarTarget(BAR_TARGET); const aggInterval = buckets.getInterval(); - $q.when(ml.getVisualizerFieldStats({ + ml.getVisualizerFieldStats({ indexPatternTitle: indexPattern.title, query: $scope.searchQuery, timeFieldName: indexPattern.timeFieldName, @@ -470,7 +471,7 @@ module samplerShardSize: $scope.samplerShardSize, interval: aggInterval.expression, fields: numberFields - })) + }) .then((resp) => { // Add the metric stats to the existing stats in the corresponding card. _.each($scope.metricCards, (card) => { @@ -520,7 +521,7 @@ module if (fields.length > 0) { - $q.when(ml.getVisualizerFieldStats({ + ml.getVisualizerFieldStats({ indexPatternTitle: indexPattern.title, query: $scope.searchQuery, fields: fields, @@ -529,7 +530,7 @@ module latest: $scope.latest, samplerShardSize: $scope.samplerShardSize, maxExamples: 10 - })) + }) .then((resp) => { // Add the metric stats to the existing stats in the corresponding card. _.each($scope.fieldCards, (card) => { @@ -575,7 +576,7 @@ module // 2. List of aggregatable fields that do not exist in docs // 3. List of non-aggregatable fields that do exist in docs. // 4. List of non-aggregatable fields that do not exist in docs. - $q.when(ml.getVisualizerOverallStats({ + ml.getVisualizerOverallStats({ indexPatternTitle: indexPattern.title, query: $scope.searchQuery, timeFieldName: indexPattern.timeFieldName, @@ -584,7 +585,7 @@ module latest: $scope.latest, aggregatableFields: aggregatableFields, nonAggregatableFields: nonAggregatableFields - })) + }) .then((resp) => { $scope.overallStats = resp; createMetricCards(); diff --git a/x-pack/plugins/ml/public/explorer/explorer.html b/x-pack/plugins/ml/public/explorer/explorer.html index 9fcf3d90b9aac8..9c6d3cb41ac6d4 100644 --- a/x-pack/plugins/ml/public/explorer/explorer.html +++ b/x-pack/plugins/ml/public/explorer/explorer.html @@ -32,18 +32,21 @@
-
+
+ +
+ +
Top Influencers - + influencers="influencers" + />
-
+
Anomaly timeline @@ -138,13 +141,10 @@

No {{swimlaneViewByFieldName}} influencers

-
- - -
+ +
diff --git a/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_config_builder.js b/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_config_builder.js index abccb6c00788fb..07a9bc0885e605 100644 --- a/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_config_builder.js +++ b/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_config_builder.js @@ -16,10 +16,9 @@ import _ from 'lodash'; import { parseInterval } from 'ui/utils/parse_interval'; import { buildConfigFromDetector } from 'plugins/ml/util/chart_config_builder'; import { mlEscape } from 'plugins/ml/util/string_utils'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; -export function explorerChartConfigBuilder(Private) { - const mlJobService = Private(JobServiceProvider); +export function explorerChartConfigBuilder() { const compiledTooltip = _.template( '
job ID: <%= jobId %>
' + diff --git a/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_directive.js b/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_directive.js index 71bfef368e78bb..98fea34be0d034 100644 --- a/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_directive.js +++ b/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_chart_directive.js @@ -18,25 +18,23 @@ import d3 from 'd3'; import angular from 'angular'; import moment from 'moment'; -import { getSeverityWithLow } from 'plugins/ml/util/anomaly_utils'; +import { formatValue } from 'plugins/ml/formatters/format_value'; +import { getSeverityWithLow } from 'plugins/ml/../common/util/anomaly_utils'; import { drawLineChartDots, numTicksForDateFormat } from 'plugins/ml/util/chart_utils'; import { TimeBuckets } from 'ui/time_buckets'; -import 'plugins/ml/filters/format_value'; import loadingIndicatorWrapperTemplate from 'plugins/ml/components/loading_indicator/loading_indicator_wrapper.html'; import { mlEscape } from 'plugins/ml/util/string_utils'; -import { FieldFormatServiceProvider } from 'plugins/ml/services/field_format_service'; +import { mlFieldFormatService } from 'plugins/ml/services/field_format_service'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); module.directive('mlExplorerChart', function ( - formatValueFilter, mlChartTooltipService, Private, mlSelectSeverityService) { function link(scope, element) { - const mlFieldFormatService = Private(FieldFormatServiceProvider); console.log('ml-explorer-chart directive link series config:', scope.seriesConfig); if (typeof scope.seriesConfig === 'undefined') { // just return so the empty directive renders without an error later on @@ -287,10 +285,10 @@ module.directive('mlExplorerChart', function ( if (_.has(marker, 'actual')) { // Display the record actual in preference to the chart value, which may be // different depending on the aggregation interval of the chart. - contents += (`
actual: ${formatValueFilter(marker.actual, config.functionDescription, fieldFormat)}`); - contents += (`
typical: ${formatValueFilter(marker.typical, config.functionDescription, fieldFormat)}`); + contents += (`
actual: ${formatValue(marker.actual, config.functionDescription, fieldFormat)}`); + contents += (`
typical: ${formatValue(marker.typical, config.functionDescription, fieldFormat)}`); } else { - contents += (`
value: ${formatValueFilter(marker.value, config.functionDescription, fieldFormat)}`); + contents += (`
value: ${formatValue(marker.value, config.functionDescription, fieldFormat)}`); if (_.has(marker, 'byFieldName') && _.has(marker, 'numberOfCauses')) { const numberOfCauses = marker.numberOfCauses; const byFieldName = mlEscape(marker.byFieldName); @@ -304,7 +302,7 @@ module.directive('mlExplorerChart', function ( } } } else { - contents += `value: ${formatValueFilter(marker.value, config.functionDescription, fieldFormat)}`; + contents += `value: ${formatValue(marker.value, config.functionDescription, fieldFormat)}`; } if (_.has(marker, 'scheduledEvents')) { diff --git a/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_charts_container_controller.js b/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_charts_container_controller.js index 442fb5e5238f59..87b61f8534cba7 100644 --- a/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_charts_container_controller.js +++ b/x-pack/plugins/ml/public/explorer/explorer_charts/explorer_charts_container_controller.js @@ -21,16 +21,13 @@ const module = uiModules.get('apps/ml'); import { explorerChartConfigBuilder } from './explorer_chart_config_builder'; import { chartLimits } from 'plugins/ml/util/chart_utils'; import { isTimeSeriesViewDetector } from 'plugins/ml/../common/util/job_utils'; -import { ResultsServiceProvider } from 'plugins/ml/services/results_service'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlResultsService } from 'plugins/ml/services/results_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; module.controller('MlExplorerChartsContainerController', function ($scope, $injector) { const Private = $injector.get('Private'); const mlExplorerDashboardService = $injector.get('mlExplorerDashboardService'); const mlSelectSeverityService = $injector.get('mlSelectSeverityService'); - const $q = $injector.get('$q'); - const mlResultsService = Private(ResultsServiceProvider); - const mlJobService = Private(JobServiceProvider); $scope.seriesToPlot = []; @@ -124,7 +121,7 @@ module.controller('MlExplorerChartsContainerController', function ($scope, $inje // only after that trigger data processing and page render. // TODO - if query returns no results e.g. source data has been deleted, // display a message saying 'No data between earliest/latest'. - const seriesPromises = seriesConfigs.map(seriesConfig => $q.all([ + const seriesPromises = seriesConfigs.map(seriesConfig => Promise.all([ getMetricData(seriesConfig, chartRange), getRecordsForCriteria(seriesConfig, chartRange), getScheduledEvents(seriesConfig, chartRange) @@ -243,7 +240,7 @@ module.controller('MlExplorerChartsContainerController', function ($scope, $inje return chartPoint; } - $q.all(seriesPromises) + Promise.all(seriesPromises) .then(response => { // calculate an overall min/max for all series const processedData = response.map(processChartData); diff --git a/x-pack/plugins/ml/public/explorer/explorer_controller.js b/x-pack/plugins/ml/public/explorer/explorer_controller.js index 6ef12e3c8a1ad7..e6636ce40a2724 100644 --- a/x-pack/plugins/ml/public/explorer/explorer_controller.js +++ b/x-pack/plugins/ml/public/explorer/explorer_controller.js @@ -18,23 +18,27 @@ import DragSelect from 'dragselect'; import moment from 'moment'; import 'plugins/ml/components/anomalies_table'; +import 'plugins/ml/components/controls'; import 'plugins/ml/components/influencers_list'; import 'plugins/ml/components/job_select_list'; import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter'; import { parseInterval } from 'ui/utils/parse_interval'; +import { initPromise } from 'plugins/ml/util/promise'; import template from './explorer.html'; import uiRoutes from 'ui/routes'; import { checkLicense } from 'plugins/ml/license/check_license'; import { checkGetJobsPrivilege } from 'plugins/ml/privilege/check_privilege'; -import { getIndexPatterns } from 'plugins/ml/util/index_utils'; +import { loadIndexPatterns, getIndexPatterns } from 'plugins/ml/util/index_utils'; import { refreshIntervalWatcher } from 'plugins/ml/util/refresh_interval_watcher'; import { IntervalHelperProvider, getBoundsRoundedToInterval } from 'plugins/ml/util/ml_time_buckets'; -import { ResultsServiceProvider } from 'plugins/ml/services/results_service'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; -import { FieldFormatServiceProvider } from 'plugins/ml/services/field_format_service'; +import { ml } from 'plugins/ml/services/ml_api_service'; +import { mlResultsService } from 'plugins/ml/services/results_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; +import { mlFieldFormatService } from 'plugins/ml/services/field_format_service'; import { JobSelectServiceProvider } from 'plugins/ml/components/job_select_list/job_select_service'; +import { isTimeSeriesViewDetector } from 'plugins/ml/../common/util/job_utils'; uiRoutes .when('/explorer/?', { @@ -42,7 +46,8 @@ uiRoutes resolve: { CheckLicense: checkLicense, privileges: checkGetJobsPrivilege, - indexPatterns: getIndexPatterns + indexPatterns: loadIndexPatterns, + initPromise: initPromise(true) } }); @@ -51,7 +56,6 @@ const module = uiModules.get('apps/ml'); module.controller('MlExplorerController', function ( $scope, - $route, $timeout, AppState, Private, @@ -59,26 +63,23 @@ module.controller('MlExplorerController', function ( mlCheckboxShowChartsService, mlExplorerDashboardService, mlSelectLimitService, + mlSelectIntervalService, mlSelectSeverityService) { $scope.timeFieldName = 'timestamp'; $scope.loading = true; - $scope.loadCounter = 0; timefilter.enableTimeRangeSelector(); timefilter.enableAutoRefreshSelector(); const TimeBuckets = Private(IntervalHelperProvider); const queryFilter = Private(FilterBarQueryFilterProvider); - const mlResultsService = Private(ResultsServiceProvider); - const mlJobService = Private(JobServiceProvider); - const mlFieldFormatService = Private(FieldFormatServiceProvider); const mlJobSelectService = Private(JobSelectServiceProvider); let resizeTimeout = null; const $mlExplorer = $('.ml-explorer'); - const MAX_INFLUENCER_FIELD_NAMES = 10; const MAX_INFLUENCER_FIELD_VALUES = 10; + const MAX_CATEGORY_EXAMPLES = 10; const VIEW_BY_JOB_LABEL = 'job ID'; const ALLOW_CELL_RANGE_SELECTION = mlExplorerDashboardService.allowCellRangeSelection; @@ -167,35 +168,34 @@ module.controller('MlExplorerController', function ( }); } - $scope.loadAnomaliesTable = function (jobIds, influencers, earliestMs, latestMs) { - mlResultsService.getRecordsForInfluencer( - jobIds, influencers, 0, earliestMs, latestMs, 500 - ) - .then((resp) => { - // Sort in descending time order before storing in scope. - $scope.anomalyRecords = _.chain(resp.records).sortBy(record => record[$scope.timeFieldName]).reverse().value(); - console.log('Explorer anomalies table data set:', $scope.anomalyRecords); - - // Need to use $timeout to ensure the broadcast happens after the child scope is updated with the new data. - $timeout(() => { - $scope.$broadcast('renderTable'); - }, 0); - }); - }; - $scope.setSelectedJobs = function (selectedIds) { let previousSelected = 0; if ($scope.selectedJobs !== null) { previousSelected = $scope.selectedJobs.length; } - // Check for any new jobs created since the page was first loaded. - for (let i = 0; i < selectedIds.length; i++) { - if (_.find($scope.jobs, { 'id': selectedIds[i] }) === undefined) { - $scope.jobs = createJobs(mlJobService.jobs); - break; + // Check for any new jobs created since the page was first loaded, + // and whether any of the jobs have influencers configured (in which + // case the Top Influencers section will be hidden). + let recreateJobs = false; + let hasInfluencers = false; + selectedIds.forEach((id) => { + if (recreateJobs === false && _.find($scope.jobs, { id }) === undefined) { + recreateJobs = true; } + + const job = mlJobService.getJob(id); + let influencers = []; + if (job !== undefined) { + influencers = job.analysis_config.influencers || []; + } + hasInfluencers = hasInfluencers || influencers.length > 0; + }); + + if (recreateJobs === true) { + $scope.jobs = createJobs(mlJobService.jobs); } + $scope.noInfluencersConfigured = !hasInfluencers; // update the jobs' selected flag $scope.selectedJobs = []; @@ -215,7 +215,7 @@ module.controller('MlExplorerController', function ( $scope.appState.save(); // Populate the map of jobs / detectors / field formatters for the selected IDs. - mlFieldFormatService.populateFormats(selectedIds, $route.current.locals.indexPatterns) + mlFieldFormatService.populateFormats(selectedIds, getIndexPatterns()) .finally(() => { // Load the data - if the FieldFormats failed to populate // the default formatting will be used for metric values. @@ -308,16 +308,39 @@ module.controller('MlExplorerController', function ( return $scope.viewBySwimlaneData !== null && $scope.viewBySwimlaneData.laneLabels && $scope.viewBySwimlaneData.laneLabels.length > 0; }; - const getTimeRange = function (cellData) { - // Time range for charts should be maximum time span at job bucket span, centred on the selected cell. + function getSelectionTimeRange(cellData) { + // Returns the time range of the cell(s) currently selected in the swimlane. + // If no cell(s) are currently selected, returns the dashboard time range. const bounds = timefilter.getActiveBounds(); - const earliestMs = cellData.time[0] !== undefined ? ((cellData.time[0]) * 1000) : bounds.min.valueOf(); - let latestMs = cellData.time[1] !== undefined ? ((cellData.time[1]) * 1000) : bounds.max.valueOf(); - if (earliestMs === latestMs) { - latestMs = latestMs + (cellData.interval * 1000); + let earliestMs = bounds.min.valueOf(); + let latestMs = bounds.max.valueOf(); + + if (cellData !== undefined && cellData.time !== undefined) { + // time property of the cell data is an array, with the elements being + // the start times of the first and last cell selected. + earliestMs = (cellData.time[0] !== undefined) ? cellData.time[0] * 1000 : bounds.min.valueOf(); + latestMs = bounds.max.valueOf(); + if (cellData.time[1] !== undefined) { + // Subtract 1 ms so search does not include start of next bucket. + latestMs = ((cellData.time[1] + cellData.interval) * 1000) - 1; + } } + return { earliestMs, latestMs }; - }; + } + + function getSelectionInfluencers(cellData) { + const influencers = []; + + if (cellData !== undefined && cellData.fieldName !== undefined && + cellData.fieldName !== VIEW_BY_JOB_LABEL) { + cellData.laneLabels.forEach((laneLabel) =>{ + influencers.push({ fieldName: $scope.swimlaneViewByFieldName, fieldValue: laneLabel }); + }); + } + + return influencers; + } // Listener for click events in the swimlane and load corresponding anomaly data. // Empty cellData is passed on clicking outside a cell with score > 0. @@ -330,33 +353,43 @@ module.controller('MlExplorerController', function ( } clearSelectedAnomalies(); } else { - let jobIds = []; - const influencers = []; - const timerange = getTimeRange(cellData); - - if (cellData.fieldName === undefined) { - // Click is in one of the cells in the Overall swimlane - reload the 'view by' swimlane - // to show the top 'view by' values for the selected time. - loadViewBySwimlaneForSelectedTime(timerange.earliestMs, timerange.latestMs); - $scope.viewByLoadedForTimeFormatted = moment(timerange.earliestMs).format('MMMM Do YYYY, HH:mm'); - } + const timerange = getSelectionTimeRange(cellData); + $scope.cellData = cellData; + + if (cellData.score > 0) { + if (cellData.fieldName === undefined) { + // Click is in one of the cells in the Overall swimlane - reload the 'view by' swimlane + // to show the top 'view by' values for the selected time. + loadViewBySwimlaneForSelectedTime(timerange.earliestMs, timerange.latestMs); + $scope.viewByLoadedForTimeFormatted = moment(timerange.earliestMs).format('MMMM Do YYYY, HH:mm'); + } + + const jobIds = (cellData.fieldName === VIEW_BY_JOB_LABEL) ? + cellData.laneLabels : $scope.getSelectedJobIds(); + const influencers = getSelectionInfluencers(cellData); - if (cellData.fieldName === VIEW_BY_JOB_LABEL) { - jobIds = cellData.laneLabels; + loadAnomaliesTableData(); + loadDataForCharts(jobIds, influencers, timerange.earliestMs, timerange.latestMs); } else { - jobIds = $scope.getSelectedJobIds(); + // Multiple cells are selected, all with a score of 0 - clear all anomalies. + $scope.$evalAsync(() => { + $scope.influencers = {}; + $scope.anomalyChartRecords = []; + + $scope.tableData = { + anomalies: [], + interval: mlSelectIntervalService.state.get('interval').val, + examplesByJobId: {}, + showViewSeriesLink: true + }; + }); - if (cellData.fieldName !== undefined) { - cellData.laneLabels.forEach((laneLabel) =>{ - influencers.push({ fieldName: $scope.swimlaneViewByFieldName, fieldValue: laneLabel }); - }); - } + mlExplorerDashboardService.anomalyDataChange.changed( + [], + timerange.earliestMs, + timerange.latestMs + ); } - - $scope.cellData = cellData; - const args = [jobIds, influencers, timerange.earliestMs, timerange.latestMs]; - $scope.loadAnomaliesTable(...args); - $scope.loadAnomaliesForCharts(...args); } }; mlExplorerDashboardService.swimlaneCellClick.watch(swimlaneCellClickListener); @@ -366,7 +399,7 @@ module.controller('MlExplorerController', function ( if (showCharts && $scope.cellData !== undefined) { swimlaneCellClickListener($scope.cellData); } else { - const timerange = getTimeRange($scope.cellData); + const timerange = getSelectionTimeRange($scope.cellData); mlExplorerDashboardService.anomalyDataChange.changed( [], timerange.earliestMs, timerange.latestMs ); @@ -377,7 +410,7 @@ module.controller('MlExplorerController', function ( const anomalyChartsSeverityListener = function () { const showCharts = mlCheckboxShowChartsService.state.get('showCharts'); if (showCharts && $scope.cellData !== undefined) { - const timerange = getTimeRange($scope.cellData); + const timerange = getSelectionTimeRange($scope.cellData); mlExplorerDashboardService.anomalyDataChange.changed( $scope.anomalyChartRecords, timerange.earliestMs, timerange.latestMs ); @@ -385,6 +418,12 @@ module.controller('MlExplorerController', function ( }; mlSelectSeverityService.state.watch(anomalyChartsSeverityListener); + const tableControlsListener = function () { + loadAnomaliesTableData(); + }; + mlSelectIntervalService.state.watch(tableControlsListener); + mlSelectSeverityService.state.watch(tableControlsListener); + const swimlaneLimitListener = function () { loadViewBySwimlane([]); clearSelectedAnomalies(); @@ -403,29 +442,93 @@ module.controller('MlExplorerController', function ( mlExplorerDashboardService.swimlaneCellClick.unwatch(swimlaneCellClickListener); mlExplorerDashboardService.swimlaneRenderDone.unwatch(swimlaneRenderDoneListener); mlSelectSeverityService.state.unwatch(anomalyChartsSeverityListener); + mlSelectIntervalService.state.unwatch(tableControlsListener); + mlSelectSeverityService.state.unwatch(tableControlsListener); mlSelectLimitService.state.unwatch(swimlaneLimitListener); - $scope.cellData = undefined; + delete $scope.cellData; refreshWatcher.cancel(); // Cancel listening for updates to the global nav state. navListener(); }); - $scope.loadAnomaliesForCharts = function (jobIds, influencers, earliestMs, latestMs) { + function loadDataForCharts(jobIds, influencers, earliestMs, latestMs) { + // Loads the data used to populate the anomaly charts and the Top Influencers List. + if (influencers.length === 0) { + getTopInfluencers(jobIds, earliestMs, latestMs); + } + // Load the top anomalies (by record_score) which will be displayed in the charts. - // TODO - combine this with loadAnomaliesTable() if the table is being retained. mlResultsService.getRecordsForInfluencer( jobIds, influencers, 0, earliestMs, latestMs, 500 - ).then((resp) => { - $scope.anomalyChartRecords = resp.records; - console.log('Explorer anomaly charts data set:', $scope.anomalyChartRecords); + ) + .then((resp) => { + if ($scope.cellData !== undefined && _.keys($scope.cellData).length > 0) { + $scope.anomalyChartRecords = resp.records; + console.log('Explorer anomaly charts data set:', $scope.anomalyChartRecords); + + if (mlCheckboxShowChartsService.state.get('showCharts')) { + mlExplorerDashboardService.anomalyDataChange.changed( + $scope.anomalyChartRecords, earliestMs, latestMs + ); + } + } - if (mlCheckboxShowChartsService.state.get('showCharts')) { - mlExplorerDashboardService.anomalyDataChange.changed( - $scope.anomalyChartRecords, earliestMs, latestMs - ); - } - }); - }; + if (influencers.length > 0) { + // Filter the Top Influencers list to show just the influencers from + // the records in the selected time range. + const recordInfluencersByName = {}; + + // Add the specified influencer(s) to ensure they are used in the filter + // even if their influencer score for the selected time range is zero. + influencers.forEach((influencer) => { + const fieldName = influencer.fieldName; + if (recordInfluencersByName[influencer.fieldName] === undefined) { + recordInfluencersByName[influencer.fieldName] = []; + } + recordInfluencersByName[fieldName].push(influencer.fieldValue); + }); + + // Add the influencers from the top scoring anomalies. + resp.records.forEach((record) => { + const influencersByName = record.influencers || []; + influencersByName.forEach((influencer) => { + const fieldName = influencer.influencer_field_name; + const fieldValues = influencer.influencer_field_values; + if (recordInfluencersByName[fieldName] === undefined) { + recordInfluencersByName[fieldName] = []; + } + recordInfluencersByName[fieldName].push(...fieldValues); + }); + }); + + const uniqValuesByName = {}; + Object.keys(recordInfluencersByName).forEach((fieldName) => { + const fieldValues = recordInfluencersByName[fieldName]; + uniqValuesByName[fieldName] = _.uniq(fieldValues); + }); + + const filterInfluencers = []; + Object.keys(uniqValuesByName).forEach((fieldName) => { + // Find record influencers with the same field name as the clicked on cell(s). + const matchingFieldName = influencers.find((influencer) => { + return influencer.fieldName === fieldName; + }); + + if (matchingFieldName !== undefined) { + // Filter for the value(s) of the clicked on cell(s). + filterInfluencers.push(...influencers); + } else { + // For other field names, add values from all records. + uniqValuesByName[fieldName].forEach((fieldValue) => { + filterInfluencers.push({ fieldName, fieldValue }); + }); + } + }); + + getTopInfluencers(jobIds, earliestMs, latestMs, filterInfluencers); + } + }); + } function loadViewBySwimlaneOptions() { // Obtain the list of 'View by' fields per job. @@ -539,36 +642,6 @@ module.controller('MlExplorerController', function ( $scope.loading = true; $scope.hasResults = false; - // Counter to keep track of what data sets have been loaded. - $scope.loadCounter++; - let awaitingCount = 2; - - // finish() function, called after each data set has been loaded and processed. - // The last one to call it will trigger the page render. - function finish(counterVar) { - awaitingCount--; - if (awaitingCount === 0 && (counterVar === $scope.loadCounter)) { - - if ($scope.overallSwimlaneData.points && $scope.overallSwimlaneData.points.length > 0) { - $scope.hasResults = true; - - // Trigger loading of the 'view by' swimlane - - // only load once the overall swimlane so that we can match the time span. - loadViewBySwimlaneOptions(); - } else { - $scope.hasResults = false; - } - $scope.loading = false; - - // Tell the result components directives to render. - // Need to use $timeout to ensure the broadcast happens after the child scope is updated with the new data. - $timeout(() => { - $scope.$broadcast('render'); - mlExplorerDashboardService.swimlaneDataChange.changed('overall'); - }, 0); - } - } - $scope.swimlaneBucketInterval = calculateSwimlaneBucketInterval(); console.log('Explorer swimlane bucketInterval:', $scope.swimlaneBucketInterval); @@ -578,25 +651,7 @@ module.controller('MlExplorerController', function ( const searchBounds = getBoundsRoundedToInterval(bounds, $scope.swimlaneBucketInterval, false); const selectedJobIds = $scope.getSelectedJobIds(); - // Query 1 - load list of top influencers. - // Pass a counter flag into the finish() function to make sure we only process the results - // for the most recent call to the load the data in cases where the job selection and time filter - // have been altered in quick succession (such as from the job picker with 'Apply time range'). - const counter = $scope.loadCounter; - mlResultsService.getTopInfluencers( - selectedJobIds, - searchBounds.min.valueOf(), - searchBounds.max.valueOf(), - MAX_INFLUENCER_FIELD_NAMES, - MAX_INFLUENCER_FIELD_VALUES - ).then((resp) => { - // TODO - sort the influencers keys so that the partition field(s) are first. - $scope.influencersData = resp.influencers; - console.log('Explorer top influencers data set:', $scope.influencersData); - finish(counter); - }); - - // Query 2 - load overall bucket scores by time. + // Load the overall bucket scores by time. // Pass the interval in seconds as the swimlane relies on a fixed number of seconds between buckets // which wouldn't be the case if e.g. '1M' was used. // Pass 'true' when obtaining bucket bounds due to the way the overall_buckets endpoint works @@ -614,11 +669,46 @@ module.controller('MlExplorerController', function ( ).then((resp) => { processOverallResults(resp.results, searchBounds); console.log('Explorer overall swimlane data set:', $scope.overallSwimlaneData); - finish(counter); + + if ($scope.overallSwimlaneData.points && $scope.overallSwimlaneData.points.length > 0) { + $scope.hasResults = true; + + // Trigger loading of the 'view by' swimlane - + // only load once the overall swimlane so that we can match the time span. + loadViewBySwimlaneOptions(); + } else { + $scope.hasResults = false; + } + $scope.loading = false; + + // Tell the result components directives to render. + // Need to use $timeout to ensure the broadcast happens after the child scope is updated with the new data. + $timeout(() => { + $scope.$broadcast('render'); + mlExplorerDashboardService.swimlaneDataChange.changed('overall'); + }, 0); }); } + function getTopInfluencers(selectedJobIds, earliestMs, latestMs, influencers = []) { + if ($scope.noInfluencersConfigured !== true) { + mlResultsService.getTopInfluencers( + selectedJobIds, + earliestMs, + latestMs, + MAX_INFLUENCER_FIELD_VALUES, + influencers + ).then((resp) => { + // TODO - sort the influencers keys so that the partition field(s) are first. + $scope.influencers = resp.influencers; + console.log('Explorer top influencers data set:', $scope.influencers); + }); + } else { + $scope.influencers = {}; + } + } + function loadViewBySwimlane(fieldValues) { // finish() function, called after each data set has been loaded and processed. // The last one to call it will trigger the page render. @@ -658,7 +748,7 @@ module.controller('MlExplorerController', function ( interval, swimlaneLimit ).then((resp) => { - processViewByResults(resp.results); + processViewByResults(resp.results, fieldValues); finish(); }); } else { @@ -670,7 +760,7 @@ module.controller('MlExplorerController', function ( interval, swimlaneLimit ).then((resp) => { - processViewByResults(resp.results); + processViewByResults(resp.results, fieldValues); finish(); }); @@ -690,7 +780,6 @@ module.controller('MlExplorerController', function ( selectedJobIds, earliestMs, latestMs, - MAX_INFLUENCER_FIELD_NAMES, swimlaneLimit ).then((resp) => { const topFieldValues = []; @@ -715,10 +804,62 @@ module.controller('MlExplorerController', function ( } } + function loadAnomaliesTableData() { + const cellData = $scope.cellData; + const jobIds = ($scope.cellData !== undefined && cellData.fieldName === VIEW_BY_JOB_LABEL) ? + cellData.laneLabels : $scope.getSelectedJobIds(); + const influencers = getSelectionInfluencers(cellData); + const timeRange = getSelectionTimeRange(cellData); + + ml.results.getAnomaliesTableData( + jobIds, + [], + influencers, + mlSelectIntervalService.state.get('interval').val, + mlSelectSeverityService.state.get('threshold').val, + timeRange.earliestMs, + timeRange.latestMs, + 500, + MAX_CATEGORY_EXAMPLES + ).then((resp) => { + const anomalies = resp.anomalies; + const detectorsByJob = mlJobService.detectorsByJob; + anomalies.forEach((anomaly) => { + // Add a detector property to each anomaly. + // Default to functionDescription if no description available. + // TODO - when job_service is moved server_side, move this to server endpoint. + const jobId = anomaly.jobId; + anomaly.detector = _.get(detectorsByJob, + [jobId, anomaly.detectorIndex, 'detector_description'], + anomaly.source.function_description); + + // Add properties used for building the links menu. + // TODO - when job_service is moved server_side, move this to server endpoint. + anomaly.isTimeSeriesViewDetector = isTimeSeriesViewDetector( + mlJobService.getJob(jobId), anomaly.detectorIndex); + if (_.has(mlJobService.customUrlsByJob, jobId)) { + anomaly.customUrls = mlJobService.customUrlsByJob[jobId]; + } + }); + + $scope.$evalAsync(() => { + $scope.tableData = { + anomalies, + interval: resp.interval, + examplesByJobId: resp.examplesByJobId, + showViewSeriesLink: true + }; + }); + + }).catch((resp) => { + console.log('Explorer - error loading data for anomalies table:', resp); + }); + } + function clearSelectedAnomalies() { $scope.anomalyChartRecords = []; - $scope.anomalyRecords = []; $scope.viewByLoadedForTimeFormatted = null; + delete $scope.cellData; // With no swimlane selection, display anomalies over all time in the table. const jobIds = $scope.getSelectedJobIds(); @@ -726,7 +867,8 @@ module.controller('MlExplorerController', function ( const earliestMs = bounds.min.valueOf(); const latestMs = bounds.max.valueOf(); mlExplorerDashboardService.anomalyDataChange.changed($scope.anomalyChartRecords, earliestMs, latestMs); - $scope.loadAnomaliesTable(jobIds, [], earliestMs, latestMs); + loadDataForCharts(jobIds, [], earliestMs, latestMs); + loadAnomaliesTableData(); } function calculateSwimlaneBucketInterval() { @@ -764,8 +906,15 @@ module.controller('MlExplorerController', function ( } function getSwimlaneContainerWidth() { - // swimlane width is 5 sixths of the window, minus 170 for the lane labels, minus 50 padding - return(($mlExplorer.width() / 6) * 5) - 170 - 50; + if ($scope.noInfluencersConfigured === true) { + // swimlane is full width, minus 30 for the 'no influencers' info icon, + // minus 170 for the lane labels, minus 50 padding + return $mlExplorer.width() - 250; + } else { + // swimlane width is 5 sixths of the window, + // minus 170 for the lane labels, minus 50 padding + return (($mlExplorer.width() / 6) * 5) - 220; + } } function processOverallResults(scoresByTime, searchBounds) { @@ -796,7 +945,11 @@ module.controller('MlExplorerController', function ( $scope.overallSwimlaneData = dataset; } - function processViewByResults(scoresByInfluencerAndTime) { + function processViewByResults(scoresByInfluencerAndTime, sortedLaneValues) { + // Processes the scores for the 'view by' swimlane. + // Sorts the lanes according to the supplied array of lane + // values in the order in which they should be displayed, + // or pass an empty array to sort lanes according to max score over all time. const dataset = { fieldName: $scope.swimlaneViewByFieldName, points: [], @@ -825,13 +978,28 @@ module.controller('MlExplorerController', function ( }); }); - // Ensure lanes are sorted in descending order of max score. - // Note the keys in scoresByInfluencerAndTime received from the ES request - // are not guaranteed to be sorted by score if they can be parsed as numbers - // (e.g. if viewing by HTTP response code). - dataset.laneLabels = laneLabels.sort((a, b) => { - return maxScoreByLaneLabel[b] - maxScoreByLaneLabel[a]; - }); + const sortValuesLength = sortedLaneValues.length; + if (sortValuesLength === 0) { + // Sort lanes in descending order of max score. + // Note the keys in scoresByInfluencerAndTime received from the ES request + // are not guaranteed to be sorted by score if they can be parsed as numbers + // (e.g. if viewing by HTTP response code). + dataset.laneLabels = laneLabels.sort((a, b) => { + return maxScoreByLaneLabel[b] - maxScoreByLaneLabel[a]; + }); + } else { + // Sort lanes according to supplied order + // e.g. when a cell in the overall swimlane has been selected. + // Find the index of each lane label from the actual data set, + // rather than using sortedLaneValues as-is, just in case they differ. + dataset.laneLabels = laneLabels.sort((a, b) => { + let aIndex = sortedLaneValues.indexOf(a); + let bIndex = sortedLaneValues.indexOf(b); + aIndex = (aIndex > -1) ? aIndex : sortValuesLength; + bIndex = (bIndex > -1) ? bIndex : sortValuesLength; + return aIndex - bIndex; + }); + } $scope.viewBySwimlaneData = dataset; } diff --git a/x-pack/plugins/ml/public/explorer/explorer_dashboard_service.js b/x-pack/plugins/ml/public/explorer/explorer_dashboard_service.js index d18fb706f0d324..f2efd703a65c38 100644 --- a/x-pack/plugins/ml/public/explorer/explorer_dashboard_service.js +++ b/x-pack/plugins/ml/public/explorer/explorer_dashboard_service.js @@ -17,7 +17,7 @@ const module = uiModules.get('apps/ml'); import { listenerFactoryProvider } from 'plugins/ml/factories/listener_factory'; module.service('mlExplorerDashboardService', function () { - this.allowCellRangeSelection = false; + this.allowCellRangeSelection = true; const listenerFactory = listenerFactoryProvider(); const dragSelect = this.dragSelect = listenerFactory(); diff --git a/x-pack/plugins/ml/public/explorer/explorer_swimlane_directive.js b/x-pack/plugins/ml/public/explorer/explorer_swimlane_directive.js index a7367266013dd0..3760c463e95638 100644 --- a/x-pack/plugins/ml/public/explorer/explorer_swimlane_directive.js +++ b/x-pack/plugins/ml/public/explorer/explorer_swimlane_directive.js @@ -15,7 +15,7 @@ import $ from 'jquery'; import moment from 'moment'; import d3 from 'd3'; -import { getSeverityColor } from 'plugins/ml/util/anomaly_utils'; +import { getSeverityColor } from 'plugins/ml/../common/util/anomaly_utils'; import { numTicksForDateFormat } from 'plugins/ml/util/chart_utils'; import { IntervalHelperProvider } from 'plugins/ml/util/ml_time_buckets'; import { mlEscape } from 'plugins/ml/util/string_utils'; diff --git a/x-pack/plugins/ml/public/explorer/styles/main.less b/x-pack/plugins/ml/public/explorer/styles/main.less index e7c254460530f4..534b8cc73a6f9e 100644 --- a/x-pack/plugins/ml/public/explorer/styles/main.less +++ b/x-pack/plugins/ml/public/explorer/styles/main.less @@ -2,7 +2,6 @@ width: 100%; display: inline-block; color: #555; - font-size: 10px; .visualize-error { h4 { @@ -35,8 +34,22 @@ } .results-container { + + .col-xs-12 { + width: calc(~"100% - 30px"); + padding-left: 10px; + } + padding: 15px 0px 15px 0px; + .no-influencers-warning { + float: left; + padding-top: 2px; + padding-left: 15px; + color: #7b8a8b; + font-size: 14px; + } + .panel-title { color: #7b8a8b; display: inline-block; @@ -319,3 +332,5 @@ } } + + diff --git a/x-pack/plugins/ml/public/factories/__tests__/state_factory.js b/x-pack/plugins/ml/public/factories/__tests__/state_factory.js index 77b4ad21000fba..d8b177301e5c96 100644 --- a/x-pack/plugins/ml/public/factories/__tests__/state_factory.js +++ b/x-pack/plugins/ml/public/factories/__tests__/state_factory.js @@ -13,9 +13,11 @@ import { stateFactoryProvider } from '../state_factory'; describe('ML - mlStateFactory', () => { let stateFactory; + let AppState; beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(($injector) => { + AppState = $injector.get('AppState'); const Private = $injector.get('Private'); stateFactory = Private(stateFactoryProvider); })); @@ -53,4 +55,49 @@ describe('ML - mlStateFactory', () => { state.set('testValue', 10); state.changed(); }); + + it(`Malformed AppState, state falls back to undefined, doesn't throw an error`, () => { + const state = stateFactory('testName'); + + // First update the state without interfering with AppState + state.set('testValue', 1); + expect(state.get('testValue')).to.be(1); + + // Manipulate AppState first, then set and get the custom state. + const appState = new AppState(); + appState.fetch(); + appState.testName = undefined; + appState.save(); + state.set('testValue', 2); + expect(state.get('testValue')).to.be(2); + + // Now set the custom state, then manipulate AppState, then get the custom state. + // Because AppState was malformed between set and get, the custom state will fallback + // to the default state, in this case undefined + state.set('testValue', 3); + appState.fetch(); + appState.testName = undefined; + appState.save(); + expect(state.get('testValue')).to.be(undefined); + }); + + it(`Malformed AppState, state falls back to default, doesn't throw an error`, () => { + const state = stateFactory('testName', { + testValue: 1 + }); + + // First update the state without interfering with AppState + state.set('testValue', 2); + expect(state.get('testValue')).to.be(2); + + // Now set the custom state, then manipulate AppState, then get the custom state. + // Because AppState was malformed between set and get, the custom state will fallback + // to the default state, in this case 1 + state.set('testValue', 3); + const appState = new AppState(); + appState.fetch(); + appState.testName = undefined; + appState.save(); + expect(state.get('testValue')).to.be(1); + }); }); diff --git a/x-pack/plugins/ml/public/factories/state_factory.js b/x-pack/plugins/ml/public/factories/state_factory.js index 6248bd92ce9f31..f9db571e70f220 100644 --- a/x-pack/plugins/ml/public/factories/state_factory.js +++ b/x-pack/plugins/ml/public/factories/state_factory.js @@ -19,11 +19,7 @@ import { listenerFactoryProvider } from './listener_factory'; // Have a look at the unit tests which demonstrate basic usage. export function stateFactoryProvider(AppState) { - return function (stateName, defaultState) { - if (typeof stateName !== 'string') { - throw 'stateName needs to be of type `string`'; - } - + function initializeAppState(stateName, defaultState) { const appState = new AppState(); appState.fetch(); @@ -49,6 +45,16 @@ export function stateFactoryProvider(AppState) { } } + return appState; + } + + return function (stateName, defaultState) { + if (typeof stateName !== 'string') { + throw 'stateName needs to be of type `string`'; + } + + let appState = initializeAppState(stateName, defaultState); + // () two times here, because the Provider first returns // the Factory, which then returns the actual listener const listener = listenerFactoryProvider()(); @@ -60,11 +66,13 @@ export function stateFactoryProvider(AppState) { // on the state. const state = { get(name) { - return appState[stateName] && appState[stateName][name]; + updateAppState(); + return appState[stateName][name]; }, // only if value doesn't match the existing one, the state gets updated // and saved. set(name, value) { + updateAppState(); if (!_.isEqual(appState[stateName][name], value)) { appState[stateName][name] = value; appState.save(); @@ -73,6 +81,7 @@ export function stateFactoryProvider(AppState) { return state; }, reset() { + updateAppState(); if (!_.isEqual(appState[stateName], defaultState)) { appState[stateName] = _.cloneDeep(defaultState); appState.save(); @@ -92,6 +101,16 @@ export function stateFactoryProvider(AppState) { } }; + // gets the current state of AppState, if for whatever reason this custom + // state isn't part of AppState anymore, reinitialize it + function updateAppState() { + appState.fetch(); + if (typeof appState[stateName] === 'undefined') { + appState = initializeAppState(stateName, defaultState); + changed = true; + } + } + return state; }; } diff --git a/x-pack/plugins/ml/public/filters/__tests__/abbreviate_whole_number.js b/x-pack/plugins/ml/public/filters/__tests__/abbreviate_whole_number.js deleted file mode 100644 index 3015b6b59cdec7..00000000000000 --- a/x-pack/plugins/ml/public/filters/__tests__/abbreviate_whole_number.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -import ngMock from 'ng_mock'; -import expect from 'expect.js'; - -let filter; - -const init = function () { - // Load the application - ngMock.module('kibana'); - - // Create the scope - ngMock.inject(function ($filter) { - filter = $filter('abbreviateWholeNumber'); - }); -}; - -describe('ML - abbreviateWholeNumber filter', () => { - - beforeEach(function () { - init(); - }); - - it('should have an abbreviateWholeNumber filter', () => { - expect(filter).to.not.be(null); - }); - - it('returns the correct format using default max digits', () => { - expect(filter(1)).to.be(1); - expect(filter(12)).to.be(12); - expect(filter(123)).to.be(123); - expect(filter(1234)).to.be('1k'); - expect(filter(12345)).to.be('12k'); - expect(filter(123456)).to.be('123k'); - expect(filter(1234567)).to.be('1m'); - expect(filter(12345678)).to.be('12m'); - expect(filter(123456789)).to.be('123m'); - expect(filter(1234567890)).to.be('1b'); - expect(filter(5555555555555.55)).to.be('6t'); - }); - - it('returns the correct format using custom max digits', () => { - expect(filter(1, 4)).to.be(1); - expect(filter(12, 4)).to.be(12); - expect(filter(123, 4)).to.be(123); - expect(filter(1234, 4)).to.be(1234); - expect(filter(12345, 4)).to.be('12k'); - expect(filter(123456, 6)).to.be(123456); - expect(filter(1234567, 4)).to.be('1m'); - expect(filter(12345678, 3)).to.be('12m'); - expect(filter(123456789, 9)).to.be(123456789); - expect(filter(1234567890, 3)).to.be('1b'); - expect(filter(5555555555555.55, 5)).to.be('6t'); - }); - -}); diff --git a/x-pack/plugins/ml/public/filters/__tests__/format_value.js b/x-pack/plugins/ml/public/filters/__tests__/format_value.js deleted file mode 100644 index 6ae77941685471..00000000000000 --- a/x-pack/plugins/ml/public/filters/__tests__/format_value.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -import ngMock from 'ng_mock'; -import expect from 'expect.js'; -import moment from 'moment'; - -let filter; - -const init = function () { - // Load the application - ngMock.module('kibana'); - - // Create the scope - ngMock.inject(function ($filter) { - filter = $filter('formatValue'); - }); -}; - -describe('ML - formatValue filter', () => { - - beforeEach(function () { - init(); - }); - - it('should have a formatValue filter', () => { - expect(filter).to.not.be(null); - }); - - // Just check the return value is in the expected format, and - // not the exact value as this will be timezone specific. - it('correctly formats time_of_week value from numeric input', () => { - const formattedValue = filter(1483228800, 'time_of_week'); - const result = moment(formattedValue, 'ddd hh:mm', true).isValid(); - expect(result).to.be(true); - }); - - it('correctly formats time_of_day value from numeric input', () => { - const formattedValue = filter(1483228800, 'time_of_day'); - const result = moment(formattedValue, 'hh:mm', true).isValid(); - expect(result).to.be(true); - }); - - it('correctly formats number values from numeric input', () => { - expect(filter(1483228800, 'mean')).to.be(1483228800); - expect(filter(1234.5678, 'mean')).to.be(1234.6); - expect(filter(0.00012345, 'mean')).to.be(0.000123); - expect(filter(0, 'mean')).to.be(0); - expect(filter(-0.12345, 'mean')).to.be(-0.123); - expect(filter(-1234.5678, 'mean')).to.be(-1234.6); - expect(filter(-100000.1, 'mean')).to.be(-100000); - }); - - it('correctly formats time_of_week value from array input', () => { - const formattedValue = filter([1483228800], 'time_of_week'); - const result = moment(formattedValue, 'ddd hh:mm', true).isValid(); - expect(result).to.be(true); - }); - - it('correctly formats time_of_day value from array input', () => { - const formattedValue = filter([1483228800], 'time_of_day'); - const result = moment(formattedValue, 'hh:mm', true).isValid(); - expect(result).to.be(true); - }); - - it('correctly formats number values from array input', () => { - expect(filter([1483228800], 'mean')).to.be(1483228800); - expect(filter([1234.5678], 'mean')).to.be(1234.6); - expect(filter([0.00012345], 'mean')).to.be(0.000123); - expect(filter([0], 'mean')).to.be(0); - expect(filter([-0.12345], 'mean')).to.be(-0.123); - expect(filter([-1234.5678], 'mean')).to.be(-1234.6); - expect(filter([-100000.1], 'mean')).to.be(-100000); - }); - - it('correctly formats multi-valued array', () => { - const result = filter([500, 1000], 'mean'); - expect(result instanceof Array).to.be(true); - expect(result.length).to.be(2); - expect(result[0]).to.be(500); - expect(result[1]).to.be(1000); - }); - -}); diff --git a/x-pack/plugins/ml/public/filters/__tests__/metric_change_description.js b/x-pack/plugins/ml/public/filters/__tests__/metric_change_description.js deleted file mode 100644 index e6045be4e09ec6..00000000000000 --- a/x-pack/plugins/ml/public/filters/__tests__/metric_change_description.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -import ngMock from 'ng_mock'; -import expect from 'expect.js'; - -let filter; - -const init = function () { - // Load the application - ngMock.module('kibana'); - - // Create the scope - ngMock.inject(function ($filter) { - filter = $filter('metricChangeDescription'); - }); -}; - -describe('ML - metricChangeDescription filter', () => { - - beforeEach(function () { - init(); - }); - - it('should have a metricChangeDescription filter', () => { - expect(filter).to.not.be(null); - }); - - it('returns correct description if actual > typical', () => { - expect(filter(1.01, 1)).to.be(' Unusually high'); - expect(filter(1.123, 1)).to.be(' 1.1x higher'); - expect(filter(2, 1)).to.be(' 2x higher'); - expect(filter(9.5, 1)).to.be(' 10x higher'); - expect(filter(1000, 1)).to.be(' More than 100x higher'); - expect(filter(1, 0)).to.be(' Unexpected non-zero value'); - }); - - it('returns correct description if actual < typical', () => { - expect(filter(1, 1.01)).to.be(' Unusually low'); - expect(filter(1, 1.123)).to.be(' 1.1x lower'); - expect(filter(1, 2)).to.be(' 2x lower'); - expect(filter(1, 9.5)).to.be(' 10x lower'); - expect(filter(1, 1000)).to.be(' More than 100x lower'); - expect(filter(0, 1)).to.be(' Unexpected zero value'); - }); - -}); diff --git a/x-pack/plugins/ml/public/filters/abbreviate_whole_number.js b/x-pack/plugins/ml/public/filters/abbreviate_whole_number.js deleted file mode 100644 index ab7d4553568136..00000000000000 --- a/x-pack/plugins/ml/public/filters/abbreviate_whole_number.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - -/* - * AngularJS filter to abbreviate large whole numbers with metric prefixes. - * Uses numeral.js to format numbers longer than the specified number of - * digits with metric abbreviations e.g. 12345 as 12k, or 98000000 as 98m. -*/ -import numeral from '@elastic/numeral'; - -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - -module.filter('abbreviateWholeNumber', function () { - return function (value, maxDigits) { - const maxNumDigits = (maxDigits !== undefined ? maxDigits : 3); - if (Math.abs(value) < Math.pow(10, maxNumDigits)) { - return value; - } else { - return numeral(value).format('0a'); - } - }; -}); - diff --git a/x-pack/plugins/ml/public/filters/format_value.js b/x-pack/plugins/ml/public/filters/format_value.js deleted file mode 100644 index 7ba54cb2311e8f..00000000000000 --- a/x-pack/plugins/ml/public/filters/format_value.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -/* - * AngularJS filter generally used for formatting 'typical' and 'actual' values - * from machine learning results. For detectors which use the time_of_week or time_of_day - * functions, the filter converts the raw number, which is the number of seconds since - * midnight, into a human-readable date/time format. - */ - -import _ from 'lodash'; -import moment from 'moment'; - -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - -module.filter('formatValue', function () { - - const SIGFIGS_IF_ROUNDING = 3; // Number of sigfigs to use for values < 10 - - function formatValue(value, fx, fieldFormat) { - // If the analysis function is time_of_week/day, format as day/time. - if (fx === 'time_of_week') { - const d = new Date(); - const i = parseInt(value); - d.setTime(i * 1000); - return moment(d).format('ddd hh:mm'); - } else if (fx === 'time_of_day') { - const d = new Date(); - const i = parseInt(value); - d.setTime(i * 1000); - return moment(d).format('hh:mm'); - } else { - if (fieldFormat !== undefined) { - return fieldFormat.convert(value, 'text'); - } else { - // If no Kibana FieldFormat object provided, - // format the value depending on its magnitude. - const absValue = Math.abs(value); - if (absValue >= 10000 || absValue === Math.floor(absValue)) { - // Output 0 decimal places if whole numbers or >= 10000 - if (fieldFormat !== undefined) { - return fieldFormat.convert(value, 'text'); - } else { - return Number(value.toFixed(0)); - } - - } else if (absValue >= 10) { - // Output to 1 decimal place between 10 and 10000 - return Number(value.toFixed(1)); - } - else { - // For values < 10, output to 3 significant figures - let multiple; - if (value > 0) { - multiple = Math.pow(10, SIGFIGS_IF_ROUNDING - Math.floor(Math.log(value) / Math.LN10) - 1); - } else { - multiple = Math.pow(10, SIGFIGS_IF_ROUNDING - Math.floor(Math.log(-1 * value) / Math.LN10) - 1); - } - return (Math.round(value * multiple)) / multiple; - } - } - } - } - - return function (value, fx, fieldFormat) { - // actual and typical values in results will be arrays. - // Unless the array is multi-valued (as it will be for multi-variate analyses), - // simply return the formatted single value. - if (Array.isArray(value)) { - if (value.length === 1) { - return formatValue(value[0], fx, fieldFormat); - } else { - return _.map(value, function (val) { return formatValue(val, fx); }); - } - } else { - return formatValue(value, fx, fieldFormat); - } - }; -}); diff --git a/x-pack/plugins/ml/public/filters/metric_change_description.js b/x-pack/plugins/ml/public/filters/metric_change_description.js deleted file mode 100644 index 8eee882bbc7e9b..00000000000000 --- a/x-pack/plugins/ml/public/filters/metric_change_description.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -/* - * AngularJS filter for producing a concise textual description of how the - * actual value compares to the typical value for a time series anomaly. - */ - -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - -module.filter('metricChangeDescription', function () { - return function (actual, typical) { - if (actual === typical) { - // Very unlikely, but just in case. - return 'actual same as typical'; - } - - // For actual / typical gives output of the form: - // 4 / 2 2x higher - // 2 / 10 5x lower - // 1000 / 1 More than 100x higher - // 999 / 1000 Unusually low - // 100 / -100 Unusually high - // 0 / 100 Unexpected zero value - // 1 / 0 Unexpected non-zero value - const isHigher = actual > typical; - const iconClass = isHigher ? 'fa-arrow-up' : 'fa-arrow-down'; - if (typical !== 0 && actual !== 0) { - const factor = isHigher ? actual / typical : typical / actual; - const direction = isHigher ? 'higher' : 'lower'; - if (factor > 1.5) { - if (factor <= 100) { - return ' ' + Math.round(factor) + 'x ' + direction; - } else { - return ' More than 100x ' + direction; - } - } - - if (factor >= 1.05) { - return ' ' + factor.toPrecision(2) + 'x ' + direction; - } else { - const dir = isHigher ? 'high' : 'low'; - return ' Unusually ' + dir; - } - - } else { - if (actual === 0) { - return ' Unexpected zero value'; - } else { - return ' Unexpected non-zero value'; - } - } - - }; -}); - diff --git a/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js b/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js new file mode 100644 index 00000000000000..582d9bac39d728 --- /dev/null +++ b/x-pack/plugins/ml/public/formatters/__tests__/abbreviate_whole_number.js @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + + +import expect from 'expect.js'; +import { abbreviateWholeNumber } from '../abbreviate_whole_number'; + +describe('ML - abbreviateWholeNumber formatter', () => { + + it('returns the correct format using default max digits', () => { + expect(abbreviateWholeNumber(1)).to.be(1); + expect(abbreviateWholeNumber(12)).to.be(12); + expect(abbreviateWholeNumber(123)).to.be(123); + expect(abbreviateWholeNumber(1234)).to.be('1k'); + expect(abbreviateWholeNumber(12345)).to.be('12k'); + expect(abbreviateWholeNumber(123456)).to.be('123k'); + expect(abbreviateWholeNumber(1234567)).to.be('1m'); + expect(abbreviateWholeNumber(12345678)).to.be('12m'); + expect(abbreviateWholeNumber(123456789)).to.be('123m'); + expect(abbreviateWholeNumber(1234567890)).to.be('1b'); + expect(abbreviateWholeNumber(5555555555555.55)).to.be('6t'); + }); + + it('returns the correct format using custom max digits', () => { + expect(abbreviateWholeNumber(1, 4)).to.be(1); + expect(abbreviateWholeNumber(12, 4)).to.be(12); + expect(abbreviateWholeNumber(123, 4)).to.be(123); + expect(abbreviateWholeNumber(1234, 4)).to.be(1234); + expect(abbreviateWholeNumber(12345, 4)).to.be('12k'); + expect(abbreviateWholeNumber(123456, 6)).to.be(123456); + expect(abbreviateWholeNumber(1234567, 4)).to.be('1m'); + expect(abbreviateWholeNumber(12345678, 3)).to.be('12m'); + expect(abbreviateWholeNumber(123456789, 9)).to.be(123456789); + expect(abbreviateWholeNumber(1234567890, 3)).to.be('1b'); + expect(abbreviateWholeNumber(5555555555555.55, 5)).to.be('6t'); + }); + +}); diff --git a/x-pack/plugins/ml/public/formatters/__tests__/format_value.js b/x-pack/plugins/ml/public/formatters/__tests__/format_value.js new file mode 100644 index 00000000000000..ff5548b73551e5 --- /dev/null +++ b/x-pack/plugins/ml/public/formatters/__tests__/format_value.js @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + + +import expect from 'expect.js'; +import moment from 'moment'; +import { formatValue } from '../format_value'; + +describe('ML - formatValue formatter', () => { + + // Just check the return value is in the expected format, and + // not the exact value as this will be timezone specific. + it('correctly formats time_of_week value from numeric input', () => { + const formattedValue = formatValue(1483228800, 'time_of_week'); + const result = moment(formattedValue, 'ddd hh:mm', true).isValid(); + expect(result).to.be(true); + }); + + it('correctly formats time_of_day value from numeric input', () => { + const formattedValue = formatValue(1483228800, 'time_of_day'); + const result = moment(formattedValue, 'hh:mm', true).isValid(); + expect(result).to.be(true); + }); + + it('correctly formats number values from numeric input', () => { + expect(formatValue(1483228800, 'mean')).to.be(1483228800); + expect(formatValue(1234.5678, 'mean')).to.be(1234.6); + expect(formatValue(0.00012345, 'mean')).to.be(0.000123); + expect(formatValue(0, 'mean')).to.be(0); + expect(formatValue(-0.12345, 'mean')).to.be(-0.123); + expect(formatValue(-1234.5678, 'mean')).to.be(-1234.6); + expect(formatValue(-100000.1, 'mean')).to.be(-100000); + }); + + it('correctly formats time_of_week value from array input', () => { + const formattedValue = formatValue([1483228800], 'time_of_week'); + const result = moment(formattedValue, 'ddd hh:mm', true).isValid(); + expect(result).to.be(true); + }); + + it('correctly formats time_of_day value from array input', () => { + const formattedValue = formatValue([1483228800], 'time_of_day'); + const result = moment(formattedValue, 'hh:mm', true).isValid(); + expect(result).to.be(true); + }); + + it('correctly formats number values from array input', () => { + expect(formatValue([1483228800], 'mean')).to.be(1483228800); + expect(formatValue([1234.5678], 'mean')).to.be(1234.6); + expect(formatValue([0.00012345], 'mean')).to.be(0.000123); + expect(formatValue([0], 'mean')).to.be(0); + expect(formatValue([-0.12345], 'mean')).to.be(-0.123); + expect(formatValue([-1234.5678], 'mean')).to.be(-1234.6); + expect(formatValue([-100000.1], 'mean')).to.be(-100000); + }); + + it('correctly formats multi-valued array', () => { + expect(formatValue([30.3, 26.2], 'lat_long')).to.be('[30.3,26.2]'); + }); + +}); diff --git a/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js b/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js new file mode 100644 index 00000000000000..9c4b1516915aaf --- /dev/null +++ b/x-pack/plugins/ml/public/formatters/__tests__/metric_change_description.js @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + + +import expect from 'expect.js'; +import { getMetricChangeDescription } from '../metric_change_description'; + + +describe('ML - metricChangeDescription formatter', () => { + + it('returns correct icon and message if actual > typical', () => { + expect(getMetricChangeDescription(1.01, 1)).to.eql({ iconType: 'sortUp', message: 'Unusually high' }); + expect(getMetricChangeDescription(1.123, 1)).to.eql({ iconType: 'sortUp', message: '1.1x higher' }); + expect(getMetricChangeDescription(2, 1)).to.eql({ iconType: 'sortUp', message: '2x higher' }); + expect(getMetricChangeDescription(9.5, 1)).to.eql({ iconType: 'sortUp', message: '10x higher' }); + expect(getMetricChangeDescription(1000, 1)).to.eql({ iconType: 'sortUp', message: 'More than 100x higher' }); + expect(getMetricChangeDescription(1, 0)).to.eql({ iconType: 'sortUp', message: 'Unexpected non-zero value' }); + }); + + it('returns correct icon and message if actual < typical', () => { + expect(getMetricChangeDescription(1, 1.01)).to.eql({ iconType: 'sortDown', message: 'Unusually low' }); + expect(getMetricChangeDescription(1, 1.123)).to.eql({ iconType: 'sortDown', message: '1.1x lower' }); + expect(getMetricChangeDescription(1, 2)).to.eql({ iconType: 'sortDown', message: '2x lower' }); + expect(getMetricChangeDescription(1, 9.5)).to.eql({ iconType: 'sortDown', message: '10x lower' }); + expect(getMetricChangeDescription(1, 1000)).to.eql({ iconType: 'sortDown', message: 'More than 100x lower' }); + expect(getMetricChangeDescription(0, 1)).to.eql({ iconType: 'sortDown', message: 'Unexpected zero value' }); + }); + +}); diff --git a/x-pack/plugins/ml/public/formatters/abbreviate_whole_number.js b/x-pack/plugins/ml/public/formatters/abbreviate_whole_number.js new file mode 100644 index 00000000000000..802aeb3a5d19c3 --- /dev/null +++ b/x-pack/plugins/ml/public/formatters/abbreviate_whole_number.js @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + +/* + * Formatter to abbreviate large whole numbers with metric prefixes. + * Uses numeral.js to format numbers longer than the specified number of + * digits with metric abbreviations e.g. 12345 as 12k, or 98000000 as 98m. +*/ +import numeral from '@elastic/numeral'; + +export function abbreviateWholeNumber(value, maxDigits) { + const maxNumDigits = (maxDigits !== undefined ? maxDigits : 3); + if (Math.abs(value) < Math.pow(10, maxNumDigits)) { + return value; + } else { + return numeral(value).format('0a'); + } +} diff --git a/x-pack/plugins/ml/public/formatters/format_value.js b/x-pack/plugins/ml/public/formatters/format_value.js new file mode 100644 index 00000000000000..40eb8202782df8 --- /dev/null +++ b/x-pack/plugins/ml/public/formatters/format_value.js @@ -0,0 +1,98 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + + +/* + * Formatter for 'typical' and 'actual' values from machine learning results. + * For detectors which use the time_of_week or time_of_day + * functions, the filter converts the raw number, which is the number of seconds since + * midnight, into a human-readable date/time format. + */ + +import moment from 'moment'; + +import { uiModules } from 'ui/modules'; +const module = uiModules.get('apps/ml'); + + +const SIGFIGS_IF_ROUNDING = 3; // Number of sigfigs to use for values < 10 + +// Formats the value of an actual or typical field from a machine learning anomaly record. +// mlFunction is the 'function' field from the ML record containing what the user entered e.g. 'high_count', +// (as opposed to the 'function_description' field which holds an ML-built display hint for the function e.g. 'count'. +export function formatValue(value, mlFunction, fieldFormat) { + // actual and typical values in anomaly record results will be arrays. + // Unless the array is multi-valued (as it will be for multi-variate analyses such as lat_long), + // simply return the formatted single value. + if (Array.isArray(value)) { + if (value.length === 1) { + return formatSingleValue(value[0], mlFunction, fieldFormat); + } else { + // Return with array style formatting. + const values = value.map(val => formatSingleValue(val, mlFunction, fieldFormat)); + return `[${values}]`; + } + } else { + return formatSingleValue(value, mlFunction, fieldFormat); + } +} + +// Formats a single value according to the specifield ML function. +// If a Kibana fieldFormat is not supplied, will fall back to default +// formatting depending on the magnitude of the value. +function formatSingleValue(value, mlFunction, fieldFormat) { + if (value === undefined || value === null) { + return ''; + } + + // If the analysis function is time_of_week/day, format as day/time. + if (mlFunction === 'time_of_week') { + const d = new Date(); + const i = parseInt(value); + d.setTime(i * 1000); + return moment(d).format('ddd hh:mm'); + } else if (mlFunction === 'time_of_day') { + const d = new Date(); + const i = parseInt(value); + d.setTime(i * 1000); + return moment(d).format('hh:mm'); + } else { + if (fieldFormat !== undefined) { + return fieldFormat.convert(value, 'text'); + } else { + // If no Kibana FieldFormat object provided, + // format the value depending on its magnitude. + const absValue = Math.abs(value); + if (absValue >= 10000 || absValue === Math.floor(absValue)) { + // Output 0 decimal places if whole numbers or >= 10000 + if (fieldFormat !== undefined) { + return fieldFormat.convert(value, 'text'); + } else { + return Number(value.toFixed(0)); + } + + } else if (absValue >= 10) { + // Output to 1 decimal place between 10 and 10000 + return Number(value.toFixed(1)); + } + else { + // For values < 10, output to 3 significant figures + let multiple; + if (value > 0) { + multiple = Math.pow(10, SIGFIGS_IF_ROUNDING - Math.floor(Math.log(value) / Math.LN10) - 1); + } else { + multiple = Math.pow(10, SIGFIGS_IF_ROUNDING - Math.floor(Math.log(-1 * value) / Math.LN10) - 1); + } + return (Math.round(value * multiple)) / multiple; + } + } + } +} + +// TODO - remove the filter once all uses of the formatValue Angular filter have been removed. +module.filter('formatValue', () => formatValue); + diff --git a/x-pack/plugins/ml/public/formatters/metric_change_description.js b/x-pack/plugins/ml/public/formatters/metric_change_description.js new file mode 100644 index 00000000000000..2edc89da376f94 --- /dev/null +++ b/x-pack/plugins/ml/public/formatters/metric_change_description.js @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + + +/* + * Produces a concise textual description of how the + * actual value compares to the typical value for an anomaly. + */ + +import { uiModules } from 'ui/modules'; +const module = uiModules.get('apps/ml'); + +// Returns an Object containing a text message and EuiIcon type to +// describe how the actual value compares to the typical. +export function getMetricChangeDescription(actualProp, typicalProp) { + if (actualProp === undefined || typicalProp === undefined) { + return { iconType: 'empty', message: '' }; + } + + let iconType; + let message; + + // For metric functions, actual and typical will be single value arrays. + let actual = actualProp; + let typical = typicalProp; + if (Array.isArray(actualProp)) { + if (actualProp.length === 1) { + actual = actualProp[0]; + } else { + // TODO - do we want to enhance the description depending on detector? + // e.g. 'Unusual location' if using a lat_long detector. + return { + iconType: 'alert', + message: 'Unusual values' + }; + } + } + + if (Array.isArray(typicalProp)) { + if (typicalProp.length === 1) { + typical = typicalProp[0]; + } + } + + if (actual === typical) { + // Very unlikely, but just in case. + message = 'actual same as typical'; + } else { + // For actual / typical gives output of the form: + // 4 / 2 2x higher + // 2 / 10 5x lower + // 1000 / 1 More than 100x higher + // 999 / 1000 Unusually low + // 100 / -100 Unusually high + // 0 / 100 Unexpected zero value + // 1 / 0 Unexpected non-zero value + const isHigher = actual > typical; + iconType = isHigher ? 'sortUp' : 'sortDown'; + if (typical !== 0 && actual !== 0) { + const factor = isHigher ? actual / typical : typical / actual; + const direction = isHigher ? 'higher' : 'lower'; + if (factor > 1.5) { + if (factor <= 100) { + message = `${Math.round(factor)}x ${direction}`; + } else { + message = `More than 100x ${direction}`; + } + } else if (factor >= 1.05) { + message = `${factor.toPrecision(2)}x ${direction}`; + } else { + message = `Unusually ${isHigher ? 'high' : 'low'}`; + } + + } else { + if (actual === 0) { + message = 'Unexpected zero value'; + } else { + message = 'Unexpected non-zero value'; + } + } + } + + return { iconType, message }; +} + +// TODO - remove the filter once all uses of the metricChangeDescription Angular filter have been removed. +module.filter('metricChangeDescription', function () { + return function (actual, typical) { + + const { + iconType, + message + } = getMetricChangeDescription(actual, typical); + + switch (iconType) { + case 'sortUp': + return ` ${message}`; + case 'sortDown': + return ` ${message}`; + case 'alert': + return ` ${message}`; + } + + return message; + }; +}); + diff --git a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/custom_url_editor_directive.js b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/custom_url_editor_directive.js index 8a2ca71bcd34e9..8fdd222cf7d506 100644 --- a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/custom_url_editor_directive.js +++ b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/custom_url_editor_directive.js @@ -33,7 +33,7 @@ module.directive('mlCustomUrlEditor', function (Private) { replace: true, transclude: true, template, - controller: function ($scope, $q) { + controller: function ($scope) { const URL_TYPE = { KIBANA_DASHBOARD: 'KIBANA_DASHBOARD', KIBANA_DISCOVER: 'KIBANA_DISCOVER', @@ -88,7 +88,7 @@ module.directive('mlCustomUrlEditor', function (Private) { }); } - $q.all([ + Promise.all([ getSavedDashboards(), getSavedIndexPatterns() ]) diff --git a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/custom_url_editor_service.js b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/custom_url_editor_service.js index 11f8fb4f8de4e2..f9bad4f31076d6 100644 --- a/x-pack/plugins/ml/public/jobs/components/custom_url_editor/custom_url_editor_service.js +++ b/x-pack/plugins/ml/public/jobs/components/custom_url_editor/custom_url_editor_service.js @@ -10,105 +10,104 @@ import { parseInterval } from 'ui/utils/parse_interval'; -import { ML_RESULTS_INDEX_PATTERN } from 'plugins/ml/constants/index_patterns'; +import { ML_RESULTS_INDEX_PATTERN } from 'plugins/ml/../common/constants/index_patterns'; import { replaceTokensInUrlValue } from 'plugins/ml/util/custom_url_utils'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; - -export function CustomUrlEditorServiceProvider(es, Private, $q) { - const mlJobService = Private(JobServiceProvider); - - // Builds the full URL for testing out a custom URL configuration, which - // may contain dollar delimited partition / influencer entity tokens and - // drilldown time range settings. - function getTestUrl(job, urlConfig) { - const urlValue = urlConfig.url_value; - const bucketSpanSecs = parseInterval(job.analysis_config.bucket_span).asSeconds(); - - // By default, return configured url_value. Look to substitute any dollar-delimited - // tokens with values from the highest scoring anomaly, or if no anomalies, with - // values from a document returned by the search in the job datafeed. - let testUrl = urlConfig.url_value; - - // Query to look for the highest scoring anomaly. - const body = { - query: { - bool: { - must: [ - { term: { job_id: job.job_id } }, - { term: { result_type: 'record' } } - ] - } - }, - size: 1, - _source: { - excludes: [] - }, - sort: [ - { record_score: { order: 'desc' } } - ] - }; - - return $q((resolve, reject) => { - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - body - }) - .then((resp) => { - if (resp.hits.total > 0) { - const record = resp.hits.hits[0]._source; - testUrl = replaceTokensInUrlValue(urlConfig, bucketSpanSecs, record, 'timestamp'); - resolve(testUrl); - } else { - // No anomalies yet for this job, so do a preview of the search - // configured in the job datafeed to obtain sample docs. - mlJobService.searchPreview(job) - .then((response) => { - let testDoc; - const docTimeFieldName = job.data_description.time_field; - - // Handle datafeeds which use aggregations or documents. - if (response.aggregations) { - // Create a dummy object which contains the fields necessary to build the URL. - const firstBucket = response.aggregations.buckets.buckets[0]; - testDoc = { - [docTimeFieldName]: firstBucket.key - }; - - // Look for bucket aggregations which match the tokens in the URL. - urlValue.replace((/\$([^?&$\'"]{1,40})\$/g), (match, name) => { - if (name !== 'earliest' && name !== 'latest' && firstBucket[name] !== undefined) { - const tokenBuckets = firstBucket[name]; - if (tokenBuckets.buckets) { - testDoc[name] = tokenBuckets.buckets[0].key; - } - } - }); +import { mlJobService } from 'plugins/ml/services/job_service'; +import { ml } from 'plugins/ml/services/ml_api_service'; + + +// Builds the full URL for testing out a custom URL configuration, which +// may contain dollar delimited partition / influencer entity tokens and +// drilldown time range settings. +function getTestUrl(job, urlConfig) { + const urlValue = urlConfig.url_value; + const bucketSpanSecs = parseInterval(job.analysis_config.bucket_span).asSeconds(); + + // By default, return configured url_value. Look to substitute any dollar-delimited + // tokens with values from the highest scoring anomaly, or if no anomalies, with + // values from a document returned by the search in the job datafeed. + let testUrl = urlConfig.url_value; + + // Query to look for the highest scoring anomaly. + const body = { + query: { + bool: { + must: [ + { term: { job_id: job.job_id } }, + { term: { result_type: 'record' } } + ] + } + }, + size: 1, + _source: { + excludes: [] + }, + sort: [ + { record_score: { order: 'desc' } } + ] + }; - } else { - if (response.hits.total > 0) { - testDoc = response.hits.hits[0]._source; + return new Promise((resolve, reject) => { + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + body + }) + .then((resp) => { + if (resp.hits.total > 0) { + const record = resp.hits.hits[0]._source; + testUrl = replaceTokensInUrlValue(urlConfig, bucketSpanSecs, record, 'timestamp'); + resolve(testUrl); + } else { + // No anomalies yet for this job, so do a preview of the search + // configured in the job datafeed to obtain sample docs. + mlJobService.searchPreview(job) + .then((response) => { + let testDoc; + const docTimeFieldName = job.data_description.time_field; + + // Handle datafeeds which use aggregations or documents. + if (response.aggregations) { + // Create a dummy object which contains the fields necessary to build the URL. + const firstBucket = response.aggregations.buckets.buckets[0]; + testDoc = { + [docTimeFieldName]: firstBucket.key + }; + + // Look for bucket aggregations which match the tokens in the URL. + urlValue.replace((/\$([^?&$\'"]{1,40})\$/g), (match, name) => { + if (name !== 'earliest' && name !== 'latest' && firstBucket[name] !== undefined) { + const tokenBuckets = firstBucket[name]; + if (tokenBuckets.buckets) { + testDoc[name] = tokenBuckets.buckets[0].key; + } } - } + }); - if (testDoc !== undefined) { - testUrl = replaceTokensInUrlValue(urlConfig, bucketSpanSecs, testDoc, docTimeFieldName); + } else { + if (response.hits.total > 0) { + testDoc = response.hits.hits[0]._source; } + } - resolve(testUrl); - - }); - } + if (testDoc !== undefined) { + testUrl = replaceTokensInUrlValue(urlConfig, bucketSpanSecs, testDoc, docTimeFieldName); + } - }) - .catch((resp) => { - reject(resp); - }); - }); + resolve(testUrl); - } + }); + } + }) + .catch((resp) => { + reject(resp); + }); + }); - return { - getTestUrl - }; } + + +export const customUrlEditorService = { + getTestUrl +}; + diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/create_watch_modal/create_watch_modal_controller.js b/x-pack/plugins/ml/public/jobs/jobs_list/create_watch_modal/create_watch_modal_controller.js index 1b61a8cb379ffd..d075af58445a98 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/create_watch_modal/create_watch_modal_controller.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/create_watch_modal/create_watch_modal_controller.js @@ -5,7 +5,8 @@ */ -import { CreateWatchServiceProvider } from 'plugins/ml/jobs/new_job/simple/components/watcher/create_watch_service'; +import { mlCreateWatchService } from 'plugins/ml/jobs/new_job/simple/components/watcher/create_watch_service'; +import { xpackFeatureProvider } from 'plugins/ml/license/check_license'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); @@ -13,14 +14,14 @@ const module = uiModules.get('apps/ml'); import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; module.controller('MlCreateWatchModal', function ($scope, $modalInstance, params, Private) { - const mlCreateWatchService = Private(CreateWatchServiceProvider); + const xpackFeature = Private(xpackFeatureProvider); const msgs = mlMessageBarService; // set a reference to the message bar service msgs.clear(); $scope.jobId = params.job.job_id; $scope.bucketSpan = params.job.analysis_config.bucket_span; - $scope.watcherEnabled = mlCreateWatchService.isWatcherEnabled(); + $scope.watcherEnabled = xpackFeature.isAvailable('watcher'); $scope.status = mlCreateWatchService.status; $scope.STATUS = mlCreateWatchService.STATUS; diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/edit_job_modal/edit_job_modal_controller.js b/x-pack/plugins/ml/public/jobs/jobs_list/edit_job_modal/edit_job_modal_controller.js index 70fe6eed0d7000..15ab9cbfc9c10d 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/edit_job_modal/edit_job_modal_controller.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/edit_job_modal/edit_job_modal_controller.js @@ -14,10 +14,10 @@ import numeral from '@elastic/numeral'; import { calculateDatafeedFrequencyDefaultSeconds } from 'plugins/ml/../common/util/job_utils'; import { parseInterval } from 'plugins/ml/../common/util/parse_interval'; -import { CustomUrlEditorServiceProvider } from 'plugins/ml/jobs/components/custom_url_editor/custom_url_editor_service'; +import { customUrlEditorService } from 'plugins/ml/jobs/components/custom_url_editor/custom_url_editor_service'; import { isWebUrl } from 'plugins/ml/util/string_utils'; import { newJobLimits } from 'plugins/ml/jobs/new_job/utils/new_job_defaults'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; import { uiModules } from 'ui/modules'; @@ -28,11 +28,9 @@ module.controller('MlEditJobModal', function ( $modalInstance, $modal, $window, - params, - Private) { + params) { const msgs = mlMessageBarService; msgs.clear(); - const mlJobService = Private(JobServiceProvider); $scope.saveLock = false; const refreshJob = params.pscope.refreshJob; @@ -152,7 +150,6 @@ module.controller('MlEditJobModal', function ( }; $scope.testCustomUrl = function (index) { - const customUrlEditorService = Private(CustomUrlEditorServiceProvider); customUrlEditorService.getTestUrl( $scope.job, $scope.job.custom_settings.custom_urls[index]) diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/edit_job_modal/styles/main.less b/x-pack/plugins/ml/public/jobs/jobs_list/edit_job_modal/styles/main.less index df57114441c8d9..d52dcdc4cef88a 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/edit_job_modal/styles/main.less +++ b/x-pack/plugins/ml/public/jobs/jobs_list/edit_job_modal/styles/main.less @@ -6,7 +6,7 @@ text-overflow: ellipsis; padding-bottom: 10px; - i[ml-info-icon] { + span[ml-info-icon] { font-size: 14px; } } diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/expanded_row.html b/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/expanded_row.html index 30b2dc30f45883..9fd22f848f31d4 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/expanded_row.html +++ b/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/expanded_row.html @@ -41,7 +41,15 @@ -
{{jobJson}}
+
@@ -115,7 +123,14 @@ is-loading="(datafeedPreview.json === '')" />
-
{{datafeedPreview.json}}
+
diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/expanded_row_directive.js b/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/expanded_row_directive.js index a76ef438007e66..c3a73fcef2cf2a 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/expanded_row_directive.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/expanded_row_directive.js @@ -8,12 +8,13 @@ import _ from 'lodash'; import moment from 'moment'; +import 'ace'; import { toLocaleString, detectorToString } from 'plugins/ml/util/string_utils'; import { copyTextToClipboard } from 'plugins/ml/util/clipboard_utils'; import { JOB_STATE, DATAFEED_STATE } from 'plugins/ml/../common/constants/states'; import { ML_DATA_PREVIEW_COUNT } from 'plugins/ml/../common/util/job_utils'; import { checkPermission } from 'plugins/ml/privilege/check_privilege'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; import numeral from '@elastic/numeral'; import chrome from 'ui/chrome'; @@ -23,7 +24,7 @@ import template from './expanded_row.html'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); -module.directive('mlJobListExpandedRow', function ($location, Private) { +module.directive('mlJobListExpandedRow', function ($location) { return { restrict: 'AE', replace: false, @@ -39,7 +40,6 @@ module.directive('mlJobListExpandedRow', function ($location, Private) { template, link: function ($scope, $element) { const msgs = mlMessageBarService; // set a reference to the message bar service - const mlJobService = Private(JobServiceProvider); const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; const DATA_FORMAT = '0.0 b'; @@ -47,6 +47,7 @@ module.directive('mlJobListExpandedRow', function ($location, Private) { $scope.permissions = { canPreviewDatafeed: checkPermission('canPreviewDatafeed') }; + $scope.jobJson = ''; $scope.toLocaleString = toLocaleString; // add toLocaleString to the scope to display nicer numbers @@ -239,6 +240,10 @@ module.directive('mlJobListExpandedRow', function ($location, Private) { return url; } + $scope.aceLoaded = function (editor) { + editor.setReadOnly(true); + $scope.$applyAsync(); + }; }, }; }) diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/forecasts_table/forecasts_table.js b/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/forecasts_table/forecasts_table.js index a46f37f8cd6392..293f89abaabe2e 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/forecasts_table/forecasts_table.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/forecasts_table/forecasts_table.js @@ -27,6 +27,7 @@ import chrome from 'ui/chrome'; import { FORECAST_REQUEST_STATE } from 'plugins/ml/../common/constants/states'; import { addItemToRecentlyAccessed } from 'plugins/ml/util/recently_accessed'; +import { mlForecastService } from 'plugins/ml/services/forecast_service'; const MAX_FORECASTS = 500; const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; @@ -47,7 +48,7 @@ class ForecastsTable extends Component { const dataCounts = this.props.job.data_counts; if (dataCounts.processed_record_count > 0) { // Get the list of all the forecasts with results at or later than the specified 'from' time. - this.props.mlForecastService.getForecastsSummary( + mlForecastService.getForecastsSummary( this.props.job, null, dataCounts.earliest_record_timestamp, @@ -247,7 +248,6 @@ class ForecastsTable extends Component { } ForecastsTable.propTypes = { job: PropTypes.object.isRequired, - mlForecastService: PropTypes.object.isRequired }; export { ForecastsTable }; diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/forecasts_table/forecasts_table_directive.js b/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/forecasts_table/forecasts_table_directive.js index f26059f24e42a4..9856c22af1737b 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/forecasts_table/forecasts_table_directive.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/forecasts_table/forecasts_table_directive.js @@ -9,22 +9,15 @@ import 'ngreact'; -import { ForecastServiceProvider } from 'plugins/ml/services/forecast_service'; - import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml', ['react']); import { ForecastsTable } from './forecasts_table'; -module.directive('mlForecastsTable', function ($injector) { - const Private = $injector.get('Private'); - const mlForecastService = Private(ForecastServiceProvider); - const reactDirective = $injector.get('reactDirective'); - +module.directive('mlForecastsTable', function (reactDirective) { return reactDirective( ForecastsTable, undefined, - { restrict: 'E' }, - { mlForecastService } + { restrict: 'E' } ); }); diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/styles/main.less b/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/styles/main.less index 7d72b377cdce55..814457a84406a1 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/styles/main.less +++ b/x-pack/plugins/ml/public/jobs/jobs_list/expanded_row/styles/main.less @@ -16,6 +16,10 @@ ml-job-list-expanded-row { padding: 10px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; + + .json-textarea { + height: 500px; + } } .job-audit-list-container { diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/job_timepicker_modal/job_timepicker_modal_controller.js b/x-pack/plugins/ml/public/jobs/jobs_list/job_timepicker_modal/job_timepicker_modal_controller.js index 5feeaeeebcf4e4..ab6351f9b92bdc 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/job_timepicker_modal/job_timepicker_modal_controller.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/job_timepicker_modal/job_timepicker_modal_controller.js @@ -9,9 +9,9 @@ import moment from 'moment'; import angular from 'angular'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; -import { CreateWatchServiceProvider } from 'plugins/ml/jobs/new_job/simple/components/watcher/create_watch_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; +import { xpackFeatureProvider } from 'plugins/ml/license/check_license'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); @@ -23,10 +23,9 @@ module.controller('MlJobTimepickerModal', function ( params, Private) { const msgs = mlMessageBarService; - const mlJobService = Private(JobServiceProvider); - const mlCreateWatchService = Private(CreateWatchServiceProvider); $scope.saveLock = false; - $scope.watcherEnabled = mlCreateWatchService.isWatcherEnabled(); + const xpackFeature = Private(xpackFeatureProvider); + $scope.watcherEnabled = xpackFeature.isAvailable('watcher'); const job = angular.copy(params.job); $scope.jobId = job.job_id; @@ -106,6 +105,7 @@ module.controller('MlJobTimepickerModal', function ( msgs.error(`Could not open ${$scope.jobId}`, resp); } } else { + // console.log(resp); msgs.error(`Could not open ${$scope.jobId}`, resp); } $scope.saveLock = false; diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/jobs_list_controller.js b/x-pack/plugins/ml/public/jobs/jobs_list/jobs_list_controller.js index fb8e3e1a99f8da..89bee73416263d 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/jobs_list_controller.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/jobs_list_controller.js @@ -32,10 +32,11 @@ import createWatchTemplate from 'plugins/ml/jobs/jobs_list/create_watch_modal/cr import { buttonsEnabledChecks } from 'plugins/ml/jobs/jobs_list/buttons_enabled_checks'; import { cloudServiceProvider } from 'plugins/ml/services/cloud_service'; import { loadNewJobDefaults } from 'plugins/ml/jobs/new_job/utils/new_job_defaults'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; -import { CalendarServiceProvider } from 'plugins/ml/services/calendar_service'; -import { JobMessagesServiceProvider } from 'plugins/ml/services/job_messages_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; +import { mlCalendarService } from 'plugins/ml/services/calendar_service'; +import { jobMessagesService } from 'plugins/ml/services/job_messages_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; +import { initPromise } from 'plugins/ml/util/promise'; uiRoutes .when('/jobs/?', { @@ -44,7 +45,8 @@ uiRoutes CheckLicense: checkLicense, privileges: checkGetJobsPrivilege, mlNodeCount: getMlNodeCount, - loadNewJobDefaults + loadNewJobDefaults, + initPromise: initPromise(true) } }); @@ -54,13 +56,10 @@ const module = uiModules.get('apps/ml', ['ui.bootstrap']); module.controller('MlJobsList', function ( $scope, - $route, $location, - $window, $timeout, $compile, $modal, - es, timefilter, kbnUrl, Private, @@ -85,9 +84,6 @@ module.controller('MlJobsList', $scope.mlNodesAvailable = mlNodesAvailable(); $scope.permissionToViewMlNodeCount = permissionToViewMlNodeCount(); - const mlJobService = Private(JobServiceProvider); - const mlCalendarService = Private(CalendarServiceProvider); - const jobMessagesService = Private(JobMessagesServiceProvider); const { isRunningOnCloud, getCloudId } = Private(cloudServiceProvider); $scope.isCloud = isRunningOnCloud(); $scope.cloudId = getCloudId(); diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/detectors_list_directive.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/detectors_list_directive.js index b708ce325c0b01..0d1badddc5e164 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/advanced/detectors_list_directive.js +++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/detectors_list_directive.js @@ -16,12 +16,12 @@ import { detectorToString } from 'plugins/ml/util/string_utils'; import template from './detectors_list.html'; import detectorModalTemplate from 'plugins/ml/jobs/new_job/advanced/detector_modal/detector_modal.html'; import detectorFilterModalTemplate from 'plugins/ml/jobs/new_job/advanced/detector_filter_modal/detector_filter_modal.html'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); -module.directive('mlJobDetectorsList', function ($modal, $q, Private) { +module.directive('mlJobDetectorsList', function ($modal) { return { restrict: 'AE', replace: true, @@ -34,7 +34,6 @@ module.directive('mlJobDetectorsList', function ($modal, $q, Private) { }, template, controller: function ($scope) { - const mlJobService = Private(JobServiceProvider); $scope.addDetector = function (dtr, index) { if (dtr !== undefined) { diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job.html b/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job.html index 20725ca195d54a..ade274940949ba 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job.html +++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job.html @@ -464,12 +464,14 @@

{{ui.pageTitle}}

- + >
@@ -482,11 +484,15 @@

{{ui.pageTitle}}

is-loading="(ui.dataPreview === '')" />
- +
Preview returns the content of the _source field only.
diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js index f8356faef62346..0b4188cad8c530 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js @@ -8,18 +8,17 @@ import _ from 'lodash'; import angular from 'angular'; +import 'ace'; import { parseInterval } from 'ui/utils/parse_interval'; -import 'ui/courier'; - import uiRoutes from 'ui/routes'; import { checkLicense } from 'plugins/ml/license/check_license'; import { checkCreateJobsPrivilege } from 'plugins/ml/privilege/check_privilege'; import template from './new_job.html'; import saveStatusTemplate from 'plugins/ml/jobs/new_job/advanced/save_status_modal/save_status_modal.html'; import { createSearchItems, createJobForSaving } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; -import { getIndexPatterns, getIndexPatternWithRoute, getSavedSearchWithRoute, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; +import { loadIndexPatterns, loadCurrentIndexPattern, loadCurrentSavedSearch, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; import { ML_JOB_FIELD_TYPES, ES_FIELD_TYPES } from 'plugins/ml/../common/constants/field_types'; import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; import { loadNewJobDefaults, newJobLimits, newJobDefaults } from 'plugins/ml/jobs/new_job/utils/new_job_defaults'; @@ -28,9 +27,10 @@ import { ML_DATA_PREVIEW_COUNT, basicJobValidation } from 'plugins/ml/../common/util/job_utils'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; import { ml } from 'plugins/ml/services/ml_api_service'; +import { initPromise } from 'plugins/ml/util/promise'; uiRoutes .when('/jobs/new_job/advanced', { @@ -38,11 +38,12 @@ uiRoutes resolve: { CheckLicense: checkLicense, privileges: checkCreateJobsPrivilege, - indexPattern: getIndexPatternWithRoute, - indexPatterns: getIndexPatterns, - savedSearch: getSavedSearchWithRoute, + indexPattern: loadCurrentIndexPattern, + indexPatterns: loadIndexPatterns, + savedSearch: loadCurrentSavedSearch, checkMlNodesAvailable, - loadNewJobDefaults + loadNewJobDefaults, + initPromise: initPromise(true) } }) .when('/jobs/new_job/advanced/:jobId', { @@ -50,11 +51,12 @@ uiRoutes resolve: { CheckLicense: checkLicense, privileges: checkCreateJobsPrivilege, - indexPattern: getIndexPatternWithRoute, - indexPatterns: getIndexPatterns, - savedSearch: getSavedSearchWithRoute, + indexPattern: loadCurrentIndexPattern, + indexPatterns: loadIndexPatterns, + savedSearch: loadCurrentSavedSearch, checkMlNodesAvailable, - loadNewJobDefaults + loadNewJobDefaults, + initPromise: initPromise(true) } }); @@ -67,15 +69,10 @@ module.controller('MlNewJob', $route, $location, $modal, - $q, - courier, - es, - Private, timefilter, mlDatafeedService, mlConfirmModalService) { - const mlJobService = Private(JobServiceProvider); timefilter.disableTimeRangeSelector(); // remove time picker from top of page timefilter.disableAutoRefreshSelector(); // remove time picker from top of page const MODE = { @@ -219,13 +216,28 @@ module.controller('MlNewJob', console.log('Editing job', mlJobService.currentJob); $scope.ui.pageTitle = 'Editing Job ' + $scope.job.job_id; } else { + // if the job_version is undefined, assume we have transferred to this page from + // a new job wizard. + // Alternatively, we are cloning a job and so the job already has a job_version if (mlJobService.currentJob.job_version === undefined) { $scope.mode = MODE.NEW; + + // if results_index_name exists, the dedicated index checkbox has been checked + if ($scope.job.results_index_name !== undefined) { + $scope.ui.useDedicatedIndex = true; + } } else { $scope.mode = MODE.CLONE; console.log('Cloning job', mlJobService.currentJob); $scope.ui.pageTitle = 'Clone Job from ' + $scope.job.job_id; $scope.job.job_id = ''; + + if ($scope.job.results_index_name === 'shared') { + delete $scope.job.results_index_name; + } else { + $scope.ui.useDedicatedIndex = true; + $scope.job.results_index_name = ''; + } } setDatafeedUIText(); setFieldDelimiterControlsFromText(); @@ -240,13 +252,6 @@ module.controller('MlNewJob', if ($scope.job.analysis_limits && $scope.job.analysis_limits.model_memory_limit) { $scope.ui.modelMemoryLimitText = $scope.job.analysis_limits.model_memory_limit; } - - if ($scope.job.results_index_name === 'shared') { - delete $scope.job.results_index_name; - } else { - $scope.ui.useDedicatedIndex = true; - $scope.job.results_index_name = ''; - } } // clear the current job @@ -296,7 +301,7 @@ module.controller('MlNewJob', }; function loadFields() { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { clear($scope.fields); clear($scope.dateFields); clear($scope.catFields); @@ -1155,6 +1160,13 @@ module.controller('MlNewJob', return _.sortBy(influencers, (inf) => inf); } + $scope.aceLoaded = function (editor) { + $scope.$applyAsync(); + if (editor.container.id === 'datafeed-preview') { + editor.setReadOnly(true); + } + }; + init(); }); diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/__snapshots__/bucket_span_estimator_view.test.js.snap b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/__snapshots__/bucket_span_estimator_view.test.js.snap new file mode 100644 index 00000000000000..e437da4d697667 --- /dev/null +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/__snapshots__/bucket_span_estimator_view.test.js.snap @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`BucketSpanEstimator renders the button 1`] = ` +
+ + + Estimate bucket span + + +
+`; + +exports[`BucketSpanEstimator renders the loading button 1`] = ` +
+ + + Estimating bucket span + + +
+`; diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator.html b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator.html deleted file mode 100644 index 8e8118c9c0aca4..00000000000000 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator.html +++ /dev/null @@ -1,13 +0,0 @@ -
- -
diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator_directive.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator_directive.js index aaf3e1772334cb..dbdb857238dae6 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator_directive.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator_directive.js @@ -4,9 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; +import ReactDOM from 'react-dom'; - -import template from './bucket_span_estimator.html'; +import { BucketSpanEstimator } from './bucket_span_estimator_view'; import { getQueryFromSavedSearch } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; import { EVENT_RATE_COUNT_FIELD } from 'plugins/ml/jobs/new_job/simple/components/constants/general'; import { ml } from 'plugins/ml/services/ml_api_service'; @@ -14,7 +15,7 @@ import { ml } from 'plugins/ml/services/ml_api_service'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); -module.directive('mlBucketSpanEstimator', function ($q) { +module.directive('mlBucketSpanEstimator', function () { return { restrict: 'AE', replace: false, @@ -26,15 +27,13 @@ module.directive('mlBucketSpanEstimator', function ($q) { ui: '=ui', exportedFunctions: '=' }, - template, - link: function ($scope) { + link: function ($scope, $element) { const STATUS = { FAILED: -1, NOT_RUNNING: 0, RUNNING: 1, FINISHED: 2 }; - $scope.STATUS = STATUS; const errorHandler = (error) => { console.log('Bucket span could not be estimated', error); @@ -78,7 +77,7 @@ module.directive('mlBucketSpanEstimator', function ($q) { }); } - $q.when(ml.estimateBucketSpan(data)) + ml.estimateBucketSpan(data) .then((interval) => { if (interval.error) { errorHandler(interval.message); @@ -101,6 +100,38 @@ module.directive('mlBucketSpanEstimator', function ($q) { $scope.exportedFunctions.guessBucketSpan = $scope.guessBucketSpan; } + // watch for these changes + $scope.$watch('formConfig.agg.type', updateButton, true); + $scope.$watch('jobStateWrapper.jobState', updateButton, true); + $scope.$watch('[ui.showJobInput,ui.formValid,ui.bucketSpanEstimator.status]', updateButton, true); + + function updateButton() { + const buttonDisabled = ( + $scope.ui.showJobInput === false || + $scope.ui.formValid === false || + $scope.formConfig.agg.type === undefined || + $scope.jobStateWrapper.jobState === $scope.JOB_STATE.RUNNING || + $scope.jobStateWrapper.jobState === $scope.JOB_STATE.STOPPING || + $scope.jobStateWrapper.jobState === $scope.JOB_STATE.FINISHED || + $scope.ui.bucketSpanEstimator.status === STATUS.RUNNING + ); + const estimatorRunning = ($scope.ui.bucketSpanEstimator.status === STATUS.RUNNING); + const buttonText = (estimatorRunning) ? 'Estimating bucket span' : 'Estimate bucket span'; + + const props = { + buttonDisabled, + estimatorRunning, + guessBucketSpan: $scope.guessBucketSpan, + buttonText + }; + + ReactDOM.render( + React.createElement(BucketSpanEstimator, props), + $element[0] + ); + } + + updateButton(); } }; }); diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator_view.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator_view.js new file mode 100644 index 00000000000000..6bc668ce16b832 --- /dev/null +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator_view.js @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import PropTypes from 'prop-types'; +import React from 'react'; + +import { + EuiButton, + EuiToolTip +} from '@elastic/eui'; + +export function BucketSpanEstimator({ buttonDisabled, buttonText, estimatorRunning, guessBucketSpan }) { + return ( +
+ + + {buttonText} + + +
+ ); +} +BucketSpanEstimator.propTypes = { + buttonDisabled: PropTypes.bool.isRequired, + buttonText: PropTypes.string.isRequired, + estimatorRunning: PropTypes.bool.isRequired, + guessBucketSpan: PropTypes.func.isRequired +}; + diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator_view.test.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator_view.test.js new file mode 100644 index 00000000000000..4ed4227977cb40 --- /dev/null +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/bucket_span_estimator_view.test.js @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { shallow } from 'enzyme'; +import React from 'react'; + +import { BucketSpanEstimator } from './bucket_span_estimator_view'; + +describe('BucketSpanEstimator', () => { + + test('renders the button', () => { + const props = { + buttonDisabled: false, + estimatorRunning: false, + guessBucketSpan: () => { }, + buttonText: 'Estimate bucket span' + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); + }); + + test('renders the loading button', () => { + const props = { + buttonDisabled: true, + estimatorRunning: true, + guessBucketSpan: () => { }, + buttonText: 'Estimating bucket span' + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/styles/main.less b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/styles/main.less index 3ef71db81a7521..eee1a2eb943ecc 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/styles/main.less +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/bucket_span_estimator/styles/main.less @@ -1,15 +1,14 @@ .bucket-span-estimator { float: right; + margin-right: 5px; + margin-top: -27px; - button { - float: right; - margin-right: 5px; - margin-top: -27px; - } - button:disabled { - background-color: #D9D9D9; - } - button.running { - color: #2D2D2D; + button.euiButton.euiButton--small { + font-size: 12px; + height: 22px; + + .euiButton__content { + padding: 2px 8px 3px; + } } } diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/post_save_options/post_save_options_directive.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/post_save_options/post_save_options_directive.js index eb285b9d86ec40..4bf8463de39347 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/post_save_options/post_save_options_directive.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/post_save_options/post_save_options_directive.js @@ -6,8 +6,9 @@ -import { PostSaveServiceProvider } from './post_save_service'; -import { CreateWatchServiceProvider } from 'plugins/ml/jobs/new_job/simple/components/watcher/create_watch_service'; +import { postSaveService } from './post_save_service'; +import { mlCreateWatchService } from 'plugins/ml/jobs/new_job/simple/components/watcher/create_watch_service'; +import { xpackFeatureProvider } from 'plugins/ml/license/check_license'; import template from './post_save_options.html'; import { uiModules } from 'ui/modules'; @@ -24,17 +25,15 @@ module.directive('mlPostSaveOptions', function (Private) { }, template, link: function ($scope) { + const xpackFeature = Private(xpackFeatureProvider); - const postSaveService = Private(PostSaveServiceProvider); - const createWatchService = Private(CreateWatchServiceProvider); - - $scope.watcherEnabled = createWatchService.isWatcherEnabled(); + $scope.watcherEnabled = xpackFeature.isAvailable('watcher'); $scope.status = postSaveService.status; $scope.STATUS = postSaveService.STATUS; - createWatchService.reset(); + mlCreateWatchService.reset(); - createWatchService.config.includeInfluencers = $scope.includeInfluencers; + mlCreateWatchService.config.includeInfluencers = $scope.includeInfluencers; $scope.runInRealtime = false; $scope.createWatch = false; $scope.embedded = true; diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/post_save_options/post_save_service.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/post_save_options/post_save_service.js index b5fd95ce9fadba..aa1f6a2e0d9107 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/post_save_options/post_save_service.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/post_save_options/post_save_service.js @@ -7,65 +7,61 @@ -import { JobServiceProvider } from 'plugins/ml/services/job_service'; -import { CreateWatchServiceProvider } from 'plugins/ml/jobs/new_job/simple/components/watcher/create_watch_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; +import { mlCreateWatchService } from 'plugins/ml/jobs/new_job/simple/components/watcher/create_watch_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; -export function PostSaveServiceProvider(Private, $q) { - const msgs = mlMessageBarService; - const mlJobService = Private(JobServiceProvider); - const createWatchService = Private(CreateWatchServiceProvider); +const msgs = mlMessageBarService; - class PostSaveService { - constructor() { - this.STATUS = { - SAVE_FAILED: -1, - SAVING: 0, - SAVED: 1, - }; +class PostSaveService { + constructor() { + this.STATUS = { + SAVE_FAILED: -1, + SAVING: 0, + SAVED: 1, + }; - this.status = { - realtimeJob: null, - watch: null - }; - createWatchService.status = this.status; + this.status = { + realtimeJob: null, + watch: null + }; + mlCreateWatchService.status = this.status; - this.externalCreateWatch; - } + this.externalCreateWatch; + } - startRealtimeJob(jobId) { - return $q((resolve, reject) => { - this.status.realtimeJob = this.STATUS.SAVING; + startRealtimeJob(jobId) { + return new Promise((resolve, reject) => { + this.status.realtimeJob = this.STATUS.SAVING; - const datafeedId = mlJobService.getDatafeedId(jobId); + const datafeedId = mlJobService.getDatafeedId(jobId); - mlJobService.openJob(jobId) - .finally(() => { - mlJobService.startDatafeed(datafeedId, jobId, 0, undefined) - .then(() => { - this.status.realtimeJob = this.STATUS.SAVED; - resolve(); - }).catch((resp) => { - msgs.error('Could not start datafeed: ', resp); - this.status.realtimeJob = this.STATUS.SAVE_FAILED; - reject(); - }); - }); + mlJobService.openJob(jobId) + .finally(() => { + mlJobService.startDatafeed(datafeedId, jobId, 0, undefined) + .then(() => { + this.status.realtimeJob = this.STATUS.SAVED; + resolve(); + }).catch((resp) => { + msgs.error('Could not start datafeed: ', resp); + this.status.realtimeJob = this.STATUS.SAVE_FAILED; + reject(); + }); + }); - }); - } + }); + } - apply(jobId, runInRealtime, createWatch) { - if (runInRealtime) { - this.startRealtimeJob(jobId) - .then(() => { - if (createWatch) { - createWatchService.createNewWatch(jobId); - } - }); - } + apply(jobId, runInRealtime, createWatch) { + if (runInRealtime) { + this.startRealtimeJob(jobId) + .then(() => { + if (createWatch) { + mlCreateWatchService.createNewWatch(jobId); + } + }); } } - - return new PostSaveService(); } + +export const postSaveService = new PostSaveService(); diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/calculate_memory_limit.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/calculate_memory_limit.js deleted file mode 100644 index e501d9864aee76..00000000000000 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/calculate_memory_limit.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - -// calculates the size of the model memory limit used in the job config -// based on the cardinality of the field being used to split the data. -// the limit should be 10MB plus 20kB per series, rounded up to the nearest MB. - -import { ml } from 'plugins/ml/services/ml_api_service'; - -export function CalculateModelMemoryLimitProvider() { - return function calculateModelMemoryLimit( - indexPattern, - splitFieldName, - query, - fieldNames, - influencerNames, - timeFieldName, - earliestMs, - latestMs) { - return ml.calculateModelMemoryLimit({ - indexPattern, - splitFieldName, - query, - fieldNames, - influencerNames, - timeFieldName, - earliestMs, - latestMs - }); - }; -} diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/chart_data_utils.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/chart_data_utils.js index 6fe10f53dfaf59..2ef3ad10088b3e 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/chart_data_utils.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/chart_data_utils.js @@ -11,16 +11,14 @@ import _ from 'lodash'; import { IntervalHelperProvider } from 'plugins/ml/util/ml_time_buckets'; import { calculateTextWidth } from 'plugins/ml/util/string_utils'; -import { ResultsServiceProvider } from 'plugins/ml/services/results_service'; -import { SimpleJobSearchServiceProvider } from 'plugins/ml/jobs/new_job/simple/components/utils/search_service'; +import { mlResultsService } from 'plugins/ml/services/results_service'; +import { mlSimpleJobSearchService } from 'plugins/ml/jobs/new_job/simple/components/utils/search_service'; -export function ChartDataUtilsProvider($q, Private, timefilter) { +export function ChartDataUtilsProvider(Private, timefilter) { const TimeBuckets = Private(IntervalHelperProvider); - const mlResultsService = Private(ResultsServiceProvider); - const mlSimpleJobSearchService = Private(SimpleJobSearchServiceProvider); function loadDocCountData(formConfig, chartData) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { // set doc count chart to be 10x less than detector charts const BAR_TARGET = Math.ceil(formConfig.chartInterval.barTarget / 10); const MAX_BARS = BAR_TARGET + (BAR_TARGET / 100) * 100; // 100% larger that bar target @@ -79,7 +77,7 @@ export function ChartDataUtilsProvider($q, Private, timefilter) { } function loadJobSwimlaneData(formConfig, chartData) { - return $q((resolve) => { + return new Promise((resolve) => { mlResultsService.getScoresByBucket( [formConfig.jobId], formConfig.start, @@ -119,7 +117,7 @@ export function ChartDataUtilsProvider($q, Private, timefilter) { } function loadDetectorSwimlaneData(formConfig, chartData) { - return $q((resolve) => { + return new Promise((resolve) => { mlSimpleJobSearchService.getScoresByRecord( formConfig.jobId, formConfig.start, diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/search_service.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/search_service.js index 292a814924c93b..b6f9723ca82a1d 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/search_service.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/utils/search_service.js @@ -8,86 +8,85 @@ import _ from 'lodash'; -import { ML_RESULTS_INDEX_PATTERN } from 'plugins/ml/constants/index_patterns'; +import { ML_RESULTS_INDEX_PATTERN } from 'plugins/ml/../common/constants/index_patterns'; import { escapeForElasticsearchQuery } from 'plugins/ml/util/string_utils'; +import { ml } from 'plugins/ml/services/ml_api_service'; -export function SimpleJobSearchServiceProvider($q, es) { - // detector swimlane search - function getScoresByRecord(jobId, earliestMs, latestMs, interval, firstSplitField) { - return $q((resolve, reject) => { - const obj = { - success: true, - results: {} - }; - - let jobIdFilterStr = 'job_id: ' + jobId; - if (firstSplitField && firstSplitField.value !== undefined) { - // Escape any reserved characters for the query_string query, - // wrapping the value in quotes to do a phrase match. - // Backslash is a special character in JSON strings, so doubly escape - // any backslash characters which exist in the field value. - jobIdFilterStr += ` AND ${escapeForElasticsearchQuery(firstSplitField.name)}:`; - jobIdFilterStr += `"${String(firstSplitField.value).replace(/\\/g, '\\\\')}"`; - } +// detector swimlane search +function getScoresByRecord(jobId, earliestMs, latestMs, interval, firstSplitField) { + return new Promise((resolve, reject) => { + const obj = { + success: true, + results: {} + }; - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: [{ - query_string: { - query: 'result_type:record' - } - }, { - bool: { - must: [{ - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } - } - }, { - query_string: { - query: jobIdFilterStr + let jobIdFilterStr = 'job_id: ' + jobId; + if (firstSplitField && firstSplitField.value !== undefined) { + // Escape any reserved characters for the query_string query, + // wrapping the value in quotes to do a phrase match. + // Backslash is a special character in JSON strings, so doubly escape + // any backslash characters which exist in the field value. + jobIdFilterStr += ` AND ${escapeForElasticsearchQuery(firstSplitField.name)}:`; + jobIdFilterStr += `"${String(firstSplitField.value).replace(/\\/g, '\\\\')}"`; + } + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: [{ + query_string: { + query: 'result_type:record' + } + }, { + bool: { + must: [{ + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' } - }] - } - }] - } - }, - aggs: { - detector_index: { - terms: { - field: 'detector_index', - order: { - recordScore: 'desc' + } + }, { + query_string: { + query: jobIdFilterStr + } + }] + } + }] + } + }, + aggs: { + detector_index: { + terms: { + field: 'detector_index', + order: { + recordScore: 'desc' + } + }, + aggs: { + recordScore: { + max: { + field: 'record_score' } }, - aggs: { - recordScore: { - max: { - field: 'record_score' + byTime: { + date_histogram: { + field: 'timestamp', + interval: interval, + min_doc_count: 1, + extended_bounds: { + min: earliestMs, + max: latestMs } }, - byTime: { - date_histogram: { - field: 'timestamp', - interval: interval, - min_doc_count: 1, - extended_bounds: { - min: earliestMs, - max: latestMs - } - }, - aggs: { - recordScore: { - max: { - field: 'record_score' - } + aggs: { + recordScore: { + max: { + field: 'record_score' } } } @@ -95,73 +94,74 @@ export function SimpleJobSearchServiceProvider($q, es) { } } } - }) - .then((resp) => { - const detectorsByIndex = _.get(resp, ['aggregations', 'detector_index', 'buckets'], []); - _.each(detectorsByIndex, (dtr) => { - const dtrResults = {}; - const dtrIndex = +dtr.key; - - const buckets = _.get(dtr, ['byTime', 'buckets'], []); - for (let j = 0; j < buckets.length; j++) { - const bkt = buckets[j]; - const time = bkt.key; - dtrResults[time] = { - recordScore: _.get(bkt, ['recordScore', 'value']), - }; - } - obj.results[dtrIndex] = dtrResults; - }); + } + }) + .then((resp) => { + const detectorsByIndex = _.get(resp, ['aggregations', 'detector_index', 'buckets'], []); + _.each(detectorsByIndex, (dtr) => { + const dtrResults = {}; + const dtrIndex = +dtr.key; - resolve(obj); - }) - .catch((resp) => { - reject(resp); + const buckets = _.get(dtr, ['byTime', 'buckets'], []); + for (let j = 0; j < buckets.length; j++) { + const bkt = buckets[j]; + const time = bkt.key; + dtrResults[time] = { + recordScore: _.get(bkt, ['recordScore', 'value']), + }; + } + obj.results[dtrIndex] = dtrResults; }); - }); - } - - function getCategoryFields(index, field, size, query) { - return $q((resolve, reject) => { - const obj = { - success: true, - results: {} - }; - - es.search({ - index, - size: 0, - body: { - query: query, - aggs: { - catFields: { - terms: { - field: field, - size: size - } + + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); +} + +function getCategoryFields(index, field, size, query) { + return new Promise((resolve, reject) => { + const obj = { + success: true, + results: {} + }; + + ml.esSearch({ + index, + size: 0, + body: { + query: query, + aggs: { + catFields: { + terms: { + field: field, + size: size } } } - }) - .then((resp) => { - obj.results.values = []; - const catFields = _.get(resp, ['aggregations', 'catFields', 'buckets'], []); - _.each(catFields, (f) => { - obj.results.values.push(f.key); - }); - - resolve(obj); - }) - .catch((resp) => { - reject(resp); + } + }) + .then((resp) => { + obj.results.values = []; + const catFields = _.get(resp, ['aggregations', 'catFields', 'buckets'], []); + _.each(catFields, (f) => { + obj.results.values.push(f.key); }); - }); - } - - return { - getScoresByRecord, - getCategoryFields - }; + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); } + +export const mlSimpleJobSearchService = { + getScoresByRecord, + getCategoryFields +}; + + diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/create_watch_directive.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/create_watch_directive.js index 1e71bcef684603..de1f0a5649066f 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/create_watch_directive.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/create_watch_directive.js @@ -8,7 +8,7 @@ import _ from 'lodash'; import { parseInterval } from 'ui/utils/parse_interval'; -import { CreateWatchServiceProvider } from 'plugins/ml/jobs/new_job/simple/components/watcher/create_watch_service'; +import { mlCreateWatchService } from 'plugins/ml/jobs/new_job/simple/components/watcher/create_watch_service'; import template from './create_watch.html'; import { ml } from 'plugins/ml/services/ml_api_service'; @@ -16,7 +16,7 @@ import { ml } from 'plugins/ml/services/ml_api_service'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); -module.directive('mlCreateWatch', function (es, $q, Private) { +module.directive('mlCreateWatch', function () { return { restrict: 'AE', replace: false, @@ -27,7 +27,6 @@ module.directive('mlCreateWatch', function (es, $q, Private) { }, template, link: function ($scope) { - const mlCreateWatchService = Private(CreateWatchServiceProvider); $scope.config = mlCreateWatchService.config; $scope.status = mlCreateWatchService.status; $scope.STATUS = mlCreateWatchService.STATUS; @@ -58,7 +57,7 @@ module.directive('mlCreateWatch', function (es, $q, Private) { } // load elasticsearch settings to see if email has been configured - $q.when(ml.getNotificationSettings()).then((resp) => { + ml.getNotificationSettings().then((resp) => { if (_.has(resp, 'defaults.xpack.notification.email')) { $scope.ui.emailEnabled = true; } diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/create_watch_service.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/create_watch_service.js index 720417b1e1baac..93152964d81cc7 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/create_watch_service.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/create_watch_service.js @@ -8,152 +8,146 @@ import chrome from 'ui/chrome'; import _ from 'lodash'; -import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info'; +import { http } from 'plugins/ml/services/http_service'; import emailBody from './email.html'; import emailInfluencersBody from './email-influencers.html'; import { watch } from './watch.js'; -export function CreateWatchServiceProvider($http, $q, Private) { - const xpackInfo = Private(XPackInfoProvider); +const compiledEmailBody = _.template(emailBody); - const compiledEmailBody = _.template(emailBody); - - const emailSection = { - send_email: { - throttle_period_in_millis: 900000, // 15m - email: { - profile: 'standard', - to: [], - subject: 'ML Watcher Alert', - body: { - html: '' - } +const emailSection = { + send_email: { + throttle_period_in_millis: 900000, // 15m + email: { + profile: 'standard', + to: [], + subject: 'ML Watcher Alert', + body: { + html: '' } } - }; - - // generate a random number between min and max - function randomNumber(min, max) { - return Math.floor(Math.random() * (max - min + 1) + min); } +}; - function saveWatch(watchModel) { - const basePath = chrome.addBasePath('/api/watcher'); - const url = `${basePath}/watch/${watchModel.id}`; +// generate a random number between min and max +function randomNumber(min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); +} - return $http.put(url, watchModel.upstreamJSON) - .catch(e => { - throw e.data.message; - }); - } +function saveWatch(watchModel) { + const basePath = chrome.addBasePath('/api/watcher'); + const url = `${basePath}/watch/${watchModel.id}`; + return http({ + url, + method: 'PUT', + data: watchModel.upstreamJSON + }); +} - class CreateWatchService { - constructor() { - this.config = {}; - this.STATUS = { - SAVE_FAILED: -1, - SAVING: 0, - SAVED: 1, - }; +class CreateWatchService { + constructor() { + this.config = {}; - this.status = { - realtimeJob: null, - watch: null - }; - } + this.STATUS = { + SAVE_FAILED: -1, + SAVING: 0, + SAVED: 1, + }; - reset() { - this.status.realtimeJob = null; - this.status.watch = null; - - this.config.id = ''; - this.config.includeEmail = false; - this.config.email = ''; - this.config.interval = '20m'; - this.config.watcherEditURL = ''; - this.config.includeInfluencers = false; - this.config.threshold = { display: 'critical', val: 75 }; - } + this.status = { + realtimeJob: null, + watch: null + }; + } - createNewWatch = function (jobId) { - return $q((resolve, reject) => { - this.status.watch = this.STATUS.SAVING; - if (jobId !== undefined) { - const id = `ml-${jobId}`; - this.config.id = id; - - // set specific properties of the the watch - watch.input.search.request.body.query.bool.filter[0].term.job_id = jobId; - watch.input.search.request.body.query.bool.filter[1].range.timestamp.gte = `now-${this.config.interval}`; - watch.input.search.request.body.aggs.bucket_results.filter.range.anomaly_score.gte = this.config.threshold.val; - - if (this.config.includeEmail && this.config.email !== '') { - const emails = this.config.email.split(','); - emailSection.send_email.email.to = emails; - - // create the html by adding the variables to the compiled email body. - emailSection.send_email.email.body.html = compiledEmailBody({ - serverAddress: chrome.getAppUrl(), - influencersSection: ((this.config.includeInfluencers === true) ? emailInfluencersBody : '') - }); + reset() { + this.status.realtimeJob = null; + this.status.watch = null; + + this.config.id = ''; + this.config.includeEmail = false; + this.config.email = ''; + this.config.interval = '20m'; + this.config.watcherEditURL = ''; + this.config.includeInfluencers = false; + this.config.threshold = { display: 'critical', val: 75 }; + } - // add email section to watch - watch.actions.send_email = emailSection.send_email; - } + createNewWatch = function (jobId) { + return new Promise((resolve, reject) => { + this.status.watch = this.STATUS.SAVING; + if (jobId !== undefined) { + const id = `ml-${jobId}`; + this.config.id = id; + + // set specific properties of the the watch + watch.input.search.request.body.query.bool.filter[0].term.job_id = jobId; + watch.input.search.request.body.query.bool.filter[1].range.timestamp.gte = `now-${this.config.interval}`; + watch.input.search.request.body.aggs.bucket_results.filter.range.anomaly_score.gte = this.config.threshold.val; + + if (this.config.includeEmail && this.config.email !== '') { + const emails = this.config.email.split(','); + emailSection.send_email.email.to = emails; + + // create the html by adding the variables to the compiled email body. + emailSection.send_email.email.body.html = compiledEmailBody({ + serverAddress: chrome.getAppUrl(), + influencersSection: ((this.config.includeInfluencers === true) ? emailInfluencersBody : '') + }); + + // add email section to watch + watch.actions.send_email = emailSection.send_email; + } - // set the trigger interval to be a random number between 60 and 120 seconds - // this is to avoid all watches firing at once if the server restarts - // and the watches synchronize - const triggerInterval = randomNumber(60, 120); - watch.trigger.schedule.interval = `${triggerInterval}s`; + // set the trigger interval to be a random number between 60 and 120 seconds + // this is to avoid all watches firing at once if the server restarts + // and the watches synchronize + const triggerInterval = randomNumber(60, 120); + watch.trigger.schedule.interval = `${triggerInterval}s`; - const watchModel = { + const watchModel = { + id, + upstreamJSON: { id, - upstreamJSON: { - id, - type: 'json', - watch - } - }; - - if (id !== '') { - saveWatch(watchModel) - .then(() => { - this.status.watch = this.STATUS.SAVED; - this.config.watcherEditURL = - `${chrome.getBasePath()}/app/kibana#/management/elasticsearch/watcher/watches/watch/${id}/edit?_g=()`; - resolve(); - }) - .catch((resp) => { - this.status.watch = this.STATUS.SAVE_FAILED; - reject(resp); - }); + type: 'json', + watch } - } else { - this.status.watch = this.STATUS.SAVE_FAILED; - reject(); + }; + + if (id !== '') { + saveWatch(watchModel) + .then(() => { + this.status.watch = this.STATUS.SAVED; + this.config.watcherEditURL = + `${chrome.getBasePath()}/app/kibana#/management/elasticsearch/watcher/watches/watch/${id}/edit?_g=()`; + resolve(); + }) + .catch((resp) => { + this.status.watch = this.STATUS.SAVE_FAILED; + reject(resp); + }); } - }); - } - - isWatcherEnabled() { - return xpackInfo.get('features.watcher.isAvailable', false); - } - - loadWatch(jobId) { - const id = `ml-${jobId}`; - const basePath = chrome.addBasePath('/api/watcher'); - const url = `${basePath}/watch/${id}`; - return $http.get(url) - .catch(e => { - throw e.data.message; - }); - } + } else { + this.status.watch = this.STATUS.SAVE_FAILED; + reject(); + } + }); } - return new CreateWatchService(); + loadWatch(jobId) { + const id = `ml-${jobId}`; + const basePath = chrome.addBasePath('/api/watcher'); + const url = `${basePath}/watch/${id}`; + return http({ + url, + method: 'GET' + }); + } } + +export const mlCreateWatchService = new CreateWatchService(); + diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/watch.js b/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/watch.js index 0ea79a4bf3a8e5..16ced43876fa2c 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/watch.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/components/watcher/watch.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ML_RESULTS_INDEX_PATTERN } from 'plugins/ml/constants/index_patterns'; +import { ML_RESULTS_INDEX_PATTERN } from 'plugins/ml/../common/constants/index_patterns'; export const watch = { trigger: { diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/create_job_controller.js index 9458b17e5a70ef..5469fb6b1989c8 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/create_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/create_job_controller.js @@ -19,7 +19,6 @@ import angular from 'angular'; import uiRoutes from 'ui/routes'; import { checkLicenseExpired } from 'plugins/ml/license/check_license'; import { checkCreateJobsPrivilege } from 'plugins/ml/privilege/check_privilege'; -import { CalculateModelMemoryLimitProvider } from 'plugins/ml/jobs/new_job/simple/components/utils/calculate_memory_limit'; import { IntervalHelperProvider } from 'plugins/ml/util/ml_time_buckets'; import { filterAggTypes } from 'plugins/ml/jobs/new_job/simple/components/utils/filter_agg_types'; import { validateJob } from 'plugins/ml/jobs/new_job/simple/components/utils/validate_job'; @@ -27,7 +26,7 @@ import { adjustIntervalDisplayed } from 'plugins/ml/jobs/new_job/simple/componen import { populateAppStateSettings } from 'plugins/ml/jobs/new_job/simple/components/utils/app_state_settings'; import { CHART_STATE, JOB_STATE } from 'plugins/ml/jobs/new_job/simple/components/constants/states'; import { createFields } from 'plugins/ml/jobs/new_job/simple/components/utils/create_fields'; -import { getIndexPatternWithRoute, getSavedSearchWithRoute, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; +import { loadCurrentIndexPattern, loadCurrentSavedSearch, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; import { ChartDataUtilsProvider } from 'plugins/ml/jobs/new_job/simple/components/utils/chart_data_utils.js'; import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; import { loadNewJobDefaults } from 'plugins/ml/jobs/new_job/utils/new_job_defaults'; @@ -37,10 +36,12 @@ import { createResultsUrl, addNewJobToRecentlyAccessed, moveToAdvancedJobCreationProvider } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { MultiMetricJobServiceProvider } from './create_job_service'; import { FullTimeRangeSelectorServiceProvider } from 'plugins/ml/components/full_time_range_selector/full_time_range_selector_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; +import { initPromise } from 'plugins/ml/util/promise'; +import { ml } from 'plugins/ml/services/ml_api_service'; import template from './create_job.html'; uiRoutes @@ -49,10 +50,11 @@ uiRoutes resolve: { CheckLicense: checkLicenseExpired, privileges: checkCreateJobsPrivilege, - indexPattern: getIndexPatternWithRoute, - savedSearch: getSavedSearchWithRoute, + indexPattern: loadCurrentIndexPattern, + savedSearch: loadCurrentSavedSearch, checkMlNodesAvailable, - loadNewJobDefaults + loadNewJobDefaults, + initPromise: initPromise(true) } }); @@ -72,9 +74,7 @@ module const msgs = mlMessageBarService; const MlTimeBuckets = Private(IntervalHelperProvider); const moveToAdvancedJobCreation = Private(moveToAdvancedJobCreationProvider); - const calculateModelMemoryLimit = Private(CalculateModelMemoryLimitProvider); const chartDataUtils = Private(ChartDataUtilsProvider); - const mlJobService = Private(JobServiceProvider); const mlMultiMetricJobService = Private(MultiMetricJobServiceProvider); const mlFullTimeRangeSelectorService = Private(FullTimeRangeSelectorServiceProvider); $scope.addNewJobToRecentlyAccessed = addNewJobToRecentlyAccessed; @@ -198,8 +198,8 @@ module query, filters, combinedQuery, - jobId: undefined, - description: undefined, + jobId: '', + description: '', jobGroups: [], useDedicatedIndex: false, isSparseData: false, @@ -641,18 +641,18 @@ module $scope.setModelMemoryLimit = function () { const formConfig = $scope.formConfig; - calculateModelMemoryLimit( - formConfig.indexPattern.title, - formConfig.splitField.name, - formConfig.query, - Object.keys(formConfig.fields), - formConfig.influencerFields.map(f => f.name), - formConfig.timeField, - formConfig.start, - formConfig.end - ) + ml.calculateModelMemoryLimit({ + indexPattern: formConfig.indexPattern.title, + splitFieldName: formConfig.splitField.name, + query: formConfig.query, + fieldNames: Object.keys(formConfig.fields), + influencerNames: formConfig.influencerFields.map(f => f.name), + timeFieldName: formConfig.timeField, + earliestMs: formConfig.start, + latestMs: formConfig.end + }) .then((resp) => { - formConfig.modelMemoryLimit = resp; + formConfig.modelMemoryLimit = resp.modelMemoryLimit; }) .catch(() => { formConfig.modelMemoryLimit = DEFAULT_MODEL_MEMORY_LIMIT; diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/create_job_service.js b/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/create_job_service.js index 4082e1088582cd..5f247542107642 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/create_job_service.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/multi_metric/create_job/create_job_service.js @@ -10,18 +10,12 @@ import _ from 'lodash'; import { EVENT_RATE_COUNT_FIELD } from 'plugins/ml/jobs/new_job/simple/components/constants/general'; import { ML_MEDIAN_PERCENTS } from 'plugins/ml/../common/util/job_utils'; -import { FieldFormatServiceProvider } from 'plugins/ml/services/field_format_service'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlFieldFormatService } from 'plugins/ml/services/field_format_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { createJobForSaving } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; +import { ml } from 'plugins/ml/services/ml_api_service'; -export function MultiMetricJobServiceProvider( - $q, - es, - timefilter, - Private) { - - const mlJobService = Private(JobServiceProvider); - const fieldFormatService = Private(FieldFormatServiceProvider); +export function MultiMetricJobServiceProvider() { class MultiMetricJobService { @@ -57,7 +51,7 @@ export function MultiMetricJobServiceProvider( } getLineChartResults(formConfig, thisLoadTimestamp) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { const fieldIds = Object.keys(formConfig.fields).sort(); @@ -80,7 +74,7 @@ export function MultiMetricJobServiceProvider( const searchJson = getSearchJsonFromConfig(formConfig); - es.search(searchJson) + ml.esSearch(searchJson) .then((resp) => { // if this is the last chart load, wipe all previous chart data if (thisLoadTimestamp === this.chartData.lastLoadTimestamp) { @@ -94,7 +88,7 @@ export function MultiMetricJobServiceProvider( if (fieldId !== EVENT_RATE_COUNT_FIELD) { const field = formConfig.fields[fieldId]; const aggType = field.agg.type.dslName; - this.chartData.detectors[fieldId].fieldFormat = fieldFormatService.getFieldFormatFromIndexPattern( + this.chartData.detectors[fieldId].fieldFormat = mlFieldFormatService.getFieldFormatFromIndexPattern( formConfig.indexPattern, fieldId, aggType); @@ -245,7 +239,7 @@ export function MultiMetricJobServiceProvider( } createJob(formConfig) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { this.job = this.getJobFromConfig(formConfig); const job = createJobForSaving(this.job); diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/create_job_controller.js index 29bd5dd3e8ea32..dad51a2f3a1483 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/create_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/create_job_controller.js @@ -26,7 +26,7 @@ import { adjustIntervalDisplayed } from 'plugins/ml/jobs/new_job/simple/componen import { populateAppStateSettings } from 'plugins/ml/jobs/new_job/simple/components/utils/app_state_settings'; import { CHART_STATE, JOB_STATE } from 'plugins/ml/jobs/new_job/simple/components/constants/states'; import { createFields } from 'plugins/ml/jobs/new_job/simple/components/utils/create_fields'; -import { getIndexPatternWithRoute, getSavedSearchWithRoute, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; +import { loadCurrentIndexPattern, loadCurrentSavedSearch, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; import { ChartDataUtilsProvider } from 'plugins/ml/jobs/new_job/simple/components/utils/chart_data_utils.js'; import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; import { loadNewJobDefaults, newJobDefaults } from 'plugins/ml/jobs/new_job/utils/new_job_defaults'; @@ -36,10 +36,11 @@ import { createResultsUrl, addNewJobToRecentlyAccessed, moveToAdvancedJobCreationProvider } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { PopulationJobServiceProvider } from './create_job_service'; import { FullTimeRangeSelectorServiceProvider } from 'plugins/ml/components/full_time_range_selector/full_time_range_selector_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; +import { initPromise } from 'plugins/ml/util/promise'; import template from './create_job.html'; uiRoutes @@ -48,10 +49,11 @@ uiRoutes resolve: { CheckLicense: checkLicenseExpired, privileges: checkCreateJobsPrivilege, - indexPattern: getIndexPatternWithRoute, - savedSearch: getSavedSearchWithRoute, + indexPattern: loadCurrentIndexPattern, + savedSearch: loadCurrentSavedSearch, checkMlNodesAvailable, - loadNewJobDefaults + loadNewJobDefaults, + initPromise: initPromise(true) } }); @@ -63,7 +65,6 @@ module $scope, $route, $timeout, - $q, timefilter, Private, AppState) { @@ -74,7 +75,6 @@ module const MlTimeBuckets = Private(IntervalHelperProvider); const moveToAdvancedJobCreation = Private(moveToAdvancedJobCreationProvider); const chartDataUtils = Private(ChartDataUtilsProvider); - const mlJobService = Private(JobServiceProvider); const mlPopulationJobService = Private(PopulationJobServiceProvider); const mlFullTimeRangeSelectorService = Private(FullTimeRangeSelectorServiceProvider); $scope.addNewJobToRecentlyAccessed = addNewJobToRecentlyAccessed; @@ -204,8 +204,8 @@ module query, filters, combinedQuery, - jobId: undefined, - description: undefined, + jobId: '', + description: '', jobGroups: [], useDedicatedIndex: false, modelMemoryLimit: DEFAULT_MODEL_MEMORY_LIMIT @@ -227,7 +227,7 @@ module }; $scope.splitChange = function (fieldIndex, splitField) { - return $q((resolve) => { + return new Promise((resolve) => { $scope.formConfig.fields[fieldIndex].firstSplitFieldName = undefined; if (splitField !== undefined) { diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/create_job_service.js b/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/create_job_service.js index adc487ad0e683f..09a2de62773aac 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/create_job_service.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/population/create_job/create_job_service.js @@ -11,20 +11,14 @@ import _ from 'lodash'; import { EVENT_RATE_COUNT_FIELD } from 'plugins/ml/jobs/new_job/simple/components/constants/general'; import { ML_MEDIAN_PERCENTS } from 'plugins/ml/../common/util/job_utils'; import { IntervalHelperProvider } from 'plugins/ml/util/ml_time_buckets'; -import { FieldFormatServiceProvider } from 'plugins/ml/services/field_format_service'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlFieldFormatService } from 'plugins/ml/services/field_format_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { createJobForSaving } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; +import { ml } from 'plugins/ml/services/ml_api_service'; +export function PopulationJobServiceProvider(timefilter, Private) { -export function PopulationJobServiceProvider( - $q, - es, - timefilter, - Private) { - - const mlJobService = Private(JobServiceProvider); const TimeBuckets = Private(IntervalHelperProvider); - const fieldFormatService = Private(FieldFormatServiceProvider); const OVER_FIELD_EXAMPLES_COUNT = 40; class PopulationJobService { @@ -61,7 +55,7 @@ export function PopulationJobServiceProvider( } getLineChartResults(formConfig, thisLoadTimestamp) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { const fieldIds = formConfig.fields.map(f => f.id); @@ -84,7 +78,7 @@ export function PopulationJobServiceProvider( const searchJson = getSearchJsonFromConfig(formConfig, timefilter, TimeBuckets); - es.search(searchJson) + ml.esSearch(searchJson) .then((resp) => { // if this is the last chart load, wipe all previous chart data if (thisLoadTimestamp === this.chartData.lastLoadTimestamp) { @@ -99,7 +93,7 @@ export function PopulationJobServiceProvider( if (fieldId !== EVENT_RATE_COUNT_FIELD) { const field = formConfig.fields[i]; const aggType = field.agg.type.dslName; - this.chartData.detectors[i].fieldFormat = fieldFormatService.getFieldFormatFromIndexPattern( + this.chartData.detectors[i].fieldFormat = mlFieldFormatService.getFieldFormatFromIndexPattern( formConfig.indexPattern, fieldId, aggType); @@ -277,7 +271,7 @@ export function PopulationJobServiceProvider( } createJob(formConfig) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { this.job = this.getJobFromConfig(formConfig); const job = createJobForSaving(this.job); diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js index b68660df0fa3a0..72661d8232b77d 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_controller.js @@ -17,12 +17,13 @@ import 'plugins/kibana/visualize/styles/main.less'; import uiRoutes from 'ui/routes'; import { checkLicenseExpired } from 'plugins/ml/license/check_license'; import { checkCreateJobsPrivilege } from 'plugins/ml/privilege/check_privilege'; -import { getIndexPatternWithRoute, getSavedSearchWithRoute } from 'plugins/ml/util/index_utils'; +import { loadCurrentIndexPattern, loadCurrentSavedSearch } from 'plugins/ml/util/index_utils'; import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { CreateRecognizerJobsServiceProvider } from './create_job_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; import { ml } from 'plugins/ml/services/ml_api_service'; +import { initPromise } from 'plugins/ml/util/promise'; import template from './create_job.html'; uiRoutes @@ -31,9 +32,10 @@ uiRoutes resolve: { CheckLicense: checkLicenseExpired, privileges: checkCreateJobsPrivilege, - indexPattern: getIndexPatternWithRoute, - savedSearch: getSavedSearchWithRoute, - checkMlNodesAvailable + indexPattern: loadCurrentIndexPattern, + savedSearch: loadCurrentSavedSearch, + checkMlNodesAvailable, + initPromise: initPromise(true) } }); @@ -45,11 +47,9 @@ module $scope, $window, $route, - $q, timefilter, Private) { - const mlJobService = Private(JobServiceProvider); const mlCreateRecognizerJobsService = Private(CreateRecognizerJobsServiceProvider); timefilter.disableTimeRangeSelector(); timefilter.disableAutoRefreshSelector(); @@ -118,11 +118,7 @@ module jobLabel: '', jobGroups: [], jobs: [], - kibanaObjects: { - dashboard: [], - search: [], - visualization: [] - }, + kibanaObjects: {}, start: 0, end: 0, query, @@ -137,9 +133,7 @@ module $scope.overallState = SAVE_STATE.NOT_SAVED; $scope.formConfig.jobs = []; $scope.formConfig.filters = []; - $scope.formConfig.kibanaObjects.dashboard = []; - $scope.formConfig.kibanaObjects.search = []; - $scope.formConfig.kibanaObjects.visualization = []; + $scope.formConfig.kibanaObjects = {}; loadJobConfigs(); }; @@ -147,7 +141,7 @@ module function loadJobConfigs() { // load the job and datafeed configs as well as the kibana saved objects // from the recognizer endpoint - $q.when(ml.getDataRecognizerModule({ moduleId })) + ml.getDataRecognizerModule({ moduleId }) .then(resp => { // populate the jobs and datafeeds if (resp.jobs && resp.jobs.length) { @@ -188,14 +182,14 @@ module // populate the kibana saved objects if (resp.kibana) { _.each(resp.kibana, (obj, key) => { - obj.forEach((o) => { - $scope.formConfig.kibanaObjects[key].push({ + $scope.formConfig.kibanaObjects[key] = obj.map((o) => { + return { id: o.id, title: o.title, saveState: SAVE_STATE.NOT_SAVED, config: o.config, exists: false - }); + }; }); }); // check to see if any of the saved objects already exist. @@ -250,7 +244,7 @@ module // call the the setupModuleConfigs endpoint to create the jobs, datafeeds and saved objects function saveDataRecognizerItems() { - return $q((resolve) => { + return new Promise((resolve) => { // set all jobs, datafeeds and saved objects to a SAVING state // i.e. display spinners setAllToSaving(); @@ -261,7 +255,7 @@ module const tempQuery = (savedSearch.id === undefined) ? undefined : combinedQuery; - $q.when(ml.setupDataRecognizerConfig({ moduleId, prefix, groups, query: tempQuery, indexPatternName })) + ml.setupDataRecognizerConfig({ moduleId, prefix, groups, query: tempQuery, indexPatternName }) .then((resp) => { if (resp.jobs) { $scope.formConfig.jobs.forEach((job) => { @@ -339,7 +333,7 @@ module } function startDatafeeds() { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { const jobs = $scope.formConfig.jobs; const numberOfJobs = jobs.length; @@ -436,7 +430,7 @@ module } function checkForSavedObject(type, savedObject) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { let exists = false; mlCreateRecognizerJobsService.loadExistingSavedObjects(type) .then((resp) => { @@ -472,6 +466,8 @@ module } else { $scope.overallState = SAVE_STATE.PARTIAL_FAILURE; } + } else { + $scope.overallState = SAVE_STATE.SAVED; } $scope.resultsUrl = createResultsUrl( diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_service.js b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_service.js index 3fcec5c6491595..751d614a68b251 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_service.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/recognize/create_job/create_job_service.js @@ -8,19 +8,18 @@ import { getQueryFromSavedSearch } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; import { SavedObjectsClientProvider } from 'ui/saved_objects'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { ml } from 'plugins/ml/services/ml_api_service'; -export function CreateRecognizerJobsServiceProvider(Private, $q) { +export function CreateRecognizerJobsServiceProvider(Private) { - const mlJobService = Private(JobServiceProvider); const savedObjectsClient = Private(SavedObjectsClientProvider); class CreateRecognizerJobsService { constructor() {} createDatafeed(job, formConfig) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { const jobId = formConfig.jobLabel + job.id; mlJobService.saveNewDatafeed(job.datafeedConfig, jobId) diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/create_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/create_job_controller.js index cba8cefa054d00..ea731a6fb3dbf6 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/create_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/create_job_controller.js @@ -28,7 +28,7 @@ import { populateAppStateSettings } from 'plugins/ml/jobs/new_job/simple/compone import { getIndexedFields } from 'plugins/ml/jobs/new_job/simple/components/utils/create_fields'; import { changeJobIDCase } from 'plugins/ml/jobs/new_job/simple/components/general_job_details/change_job_id_case'; import { CHART_STATE, JOB_STATE } from 'plugins/ml/jobs/new_job/simple/components/constants/states'; -import { getIndexPatternWithRoute, getSavedSearchWithRoute, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; +import { loadCurrentIndexPattern, loadCurrentSavedSearch, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; import { loadNewJobDefaults } from 'plugins/ml/jobs/new_job/utils/new_job_defaults'; import { @@ -36,10 +36,11 @@ import { createResultsUrl, addNewJobToRecentlyAccessed, moveToAdvancedJobCreationProvider } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { SingleMetricJobServiceProvider } from './create_job_service'; import { FullTimeRangeSelectorServiceProvider } from 'plugins/ml/components/full_time_range_selector/full_time_range_selector_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; +import { initPromise } from 'plugins/ml/util/promise'; import template from './create_job.html'; @@ -49,10 +50,11 @@ uiRoutes resolve: { CheckLicense: checkLicenseExpired, privileges: checkCreateJobsPrivilege, - indexPattern: getIndexPatternWithRoute, - savedSearch: getSavedSearchWithRoute, + indexPattern: loadCurrentIndexPattern, + savedSearch: loadCurrentSavedSearch, checkMlNodesAvailable, - loadNewJobDefaults + loadNewJobDefaults, + initPromise: initPromise(true) } }); @@ -64,7 +66,6 @@ module $scope, $route, $filter, - $q, timefilter, Private, AppState) { @@ -74,7 +75,6 @@ module const msgs = mlMessageBarService; const MlTimeBuckets = Private(IntervalHelperProvider); const moveToAdvancedJobCreation = Private(moveToAdvancedJobCreationProvider); - const mlJobService = Private(JobServiceProvider); const mlSingleMetricJobService = Private(SingleMetricJobServiceProvider); const mlFullTimeRangeSelectorService = Private(FullTimeRangeSelectorServiceProvider); @@ -201,8 +201,8 @@ module query, filters, combinedQuery, - jobId: undefined, - description: undefined, + jobId: '', + description: '', jobGroups: [], useDedicatedIndex: false, isSparseData: false, diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/create_job_service.js b/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/create_job_service.js index e54c5d03628805..398a072defe5bb 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/create_job_service.js +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/create_job_service.js @@ -12,19 +12,13 @@ import { parseInterval } from 'ui/utils/parse_interval'; import { ML_MEDIAN_PERCENTS } from 'plugins/ml/../common/util/job_utils'; import { calculateTextWidth } from 'plugins/ml/util/string_utils'; -import { FieldFormatServiceProvider } from 'plugins/ml/services/field_format_service'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; -import { ResultsServiceProvider } from 'plugins/ml/services/results_service'; +import { mlFieldFormatService } from 'plugins/ml/services/field_format_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; +import { mlResultsService } from 'plugins/ml/services/results_service'; import { createJobForSaving } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; +import { ml } from 'plugins/ml/services/ml_api_service'; -export function SingleMetricJobServiceProvider( - $q, - es, - Private) { - - const mlJobService = Private(JobServiceProvider); - const mlResultsService = Private(ResultsServiceProvider); - const fieldFormatService = Private(FieldFormatServiceProvider); +export function SingleMetricJobServiceProvider() { class SingleMetricJobService { @@ -43,7 +37,7 @@ export function SingleMetricJobServiceProvider( } getLineChartResults(formConfig) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { this.chartData.line = []; this.chartData.model = []; @@ -56,7 +50,7 @@ export function SingleMetricJobServiceProvider( const aggType = formConfig.agg.type.dslName; if (formConfig.field && formConfig.field.id) { - this.chartData.fieldFormat = fieldFormatService.getFieldFormatFromIndexPattern( + this.chartData.fieldFormat = mlFieldFormatService.getFieldFormatFromIndexPattern( formConfig.indexPattern, formConfig.field.id, aggType); @@ -71,7 +65,7 @@ export function SingleMetricJobServiceProvider( const searchJson = getSearchJsonFromConfig(formConfig); - es.search(searchJson) + ml.esSearch(searchJson) .then((resp) => { const aggregationsByTime = _.get(resp, ['aggregations', 'times', 'buckets'], []); @@ -271,7 +265,7 @@ export function SingleMetricJobServiceProvider( } createJob(formConfig) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { this.job = this.getJobFromConfig(formConfig); const job = createJobForSaving(this.job); @@ -304,7 +298,7 @@ export function SingleMetricJobServiceProvider( } loadModelData(formConfig) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { let start = formConfig.start; @@ -362,7 +356,7 @@ export function SingleMetricJobServiceProvider( } loadSwimlaneData(formConfig) { - return $q((resolve) => { + return new Promise((resolve) => { mlResultsService.getScoresByBucket( [formConfig.jobId], diff --git a/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/styles/main.less b/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/styles/main.less index b8997e3aeabbb9..3a3494aea72446 100755 --- a/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/styles/main.less +++ b/x-pack/plugins/ml/public/jobs/new_job/simple/single_metric/create_job/styles/main.less @@ -19,10 +19,9 @@ .form-controls { .bucket-span-container { white-space: nowrap; + width: calc(~"100% - 40px"); .bucket-span-input { - width: calc(~"100% - 40px"); - display: inline-block; background-color: transparent; float: left; } @@ -31,12 +30,6 @@ background-color: #D9D9D9; } - .bucket-span-estimator { - button { - margin-right: 45px; - } - } - .validation-error { margin-bottom: -25px; } diff --git a/x-pack/plugins/ml/public/jobs/new_job/utils/new_job_utils.js b/x-pack/plugins/ml/public/jobs/new_job/utils/new_job_utils.js index 9a2b196aefca8f..abff9b7ddd222d 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/utils/new_job_utils.js +++ b/x-pack/plugins/ml/public/jobs/new_job/utils/new_job_utils.js @@ -10,7 +10,7 @@ import _ from 'lodash'; import moment from 'moment'; import { migrateFilter } from 'ui/courier/data_source/_migrate_filter.js'; import { addItemToRecentlyAccessed } from 'plugins/ml/util/recently_accessed'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; export function getQueryFromSavedSearch(formConfig) { const must = []; @@ -115,8 +115,7 @@ export function addNewJobToRecentlyAccessed(jobId, resultsUrl) { addItemToRecentlyAccessed(urlParts[1], jobId, urlParts[2]); } -export function moveToAdvancedJobCreationProvider(Private, $location) { - const mlJobService = Private(JobServiceProvider); +export function moveToAdvancedJobCreationProvider($location) { return function moveToAdvancedJobCreation(job) { mlJobService.currentJob = job; $location.path('jobs/new_job/advanced'); diff --git a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js index 9a1451fa3cf6bb..124966115aa5fa 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/index_or_search/index_or_search_controller.js @@ -15,8 +15,9 @@ import uiRoutes from 'ui/routes'; import { checkLicenseExpired } from 'plugins/ml/license/check_license'; import { preConfiguredJobRedirect } from 'plugins/ml/jobs/new_job/wizard/preconfigured_job_redirect'; import { checkCreateJobsPrivilege } from 'plugins/ml/privilege/check_privilege'; -import { getIndexPatterns } from 'plugins/ml/util/index_utils'; +import { loadIndexPatterns, getIndexPatterns } from 'plugins/ml/util/index_utils'; import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; +import { initPromise } from 'plugins/ml/util/promise'; import template from './index_or_search.html'; uiRoutes @@ -30,9 +31,10 @@ uiRoutes resolve: { CheckLicense: checkLicenseExpired, privileges: checkCreateJobsPrivilege, - indexPatterns: getIndexPatterns, + indexPatterns: loadIndexPatterns, preConfiguredJobRedirect, - checkMlNodesAvailable + checkMlNodesAvailable, + initPromise: initPromise(true) } }); @@ -48,7 +50,7 @@ module.controller('MlNewJobStepIndexOrSearch', timefilter.disableTimeRangeSelector(); // remove time picker from top of page timefilter.disableAutoRefreshSelector(); // remove time picker from top of page - $scope.indexPatterns = $route.current.locals.indexPatterns; + $scope.indexPatterns = getIndexPatterns(); $scope.withIndexPatternUrl = function (pattern) { if (!pattern) { diff --git a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/job_type.html b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/job_type.html index 69eb88b08d5888..180d3f9adbaa06 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/job_type.html +++ b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/job_type.html @@ -64,7 +64,7 @@

Use a wizard

- Single metric job + Single metric job

Single metric

@@ -85,7 +85,7 @@

Single metric

- Multi metric job + Multi metric job

Multi metric

@@ -106,7 +106,7 @@

Multi metric

- Population job + Population job

Population

@@ -127,7 +127,7 @@

Population

- Advanced job + Advanced job

Advanced

@@ -165,7 +165,7 @@

Learn more about your data

- Single metric job + Single metric job

Data Visualizer

diff --git a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/job_type_controller.js b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/job_type_controller.js index e7890493e987af..02badffdaf2db9 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/job_type_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/wizard/steps/job_type/job_type_controller.js @@ -16,9 +16,10 @@ import uiRoutes from 'ui/routes'; import { checkLicenseExpired } from 'plugins/ml/license/check_license'; import { checkCreateJobsPrivilege } from 'plugins/ml/privilege/check_privilege'; import { createSearchItems } from 'plugins/ml/jobs/new_job/utils/new_job_utils'; -import { getIndexPatternWithRoute, getSavedSearchWithRoute, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; +import { loadCurrentIndexPattern, loadCurrentSavedSearch, timeBasedIndexCheck } from 'plugins/ml/util/index_utils'; import { addItemToRecentlyAccessed } from 'plugins/ml/util/recently_accessed'; import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; +import { initPromise } from 'plugins/ml/util/promise'; import template from './job_type.html'; uiRoutes @@ -27,9 +28,10 @@ uiRoutes resolve: { CheckLicense: checkLicenseExpired, privileges: checkCreateJobsPrivilege, - indexPattern: getIndexPatternWithRoute, - savedSearch: getSavedSearchWithRoute, - checkMlNodesAvailable + indexPattern: loadCurrentIndexPattern, + savedSearch: loadCurrentSavedSearch, + checkMlNodesAvailable, + initPromise: initPromise(true) } }); diff --git a/x-pack/plugins/ml/public/license/check_license.js b/x-pack/plugins/ml/public/license/check_license.js index 9d78fa22025275..59d18e71485933 100644 --- a/x-pack/plugins/ml/public/license/check_license.js +++ b/x-pack/plugins/ml/public/license/check_license.js @@ -14,7 +14,7 @@ import chrome from 'ui/chrome'; let licenseHasExpired = true; -export function checkLicense(Private, Promise, kbnBaseUrl) { +export function checkLicense(Private, kbnBaseUrl) { const xpackInfo = Private(XPackInfoProvider); const features = xpackInfo.get('features.ml'); @@ -67,3 +67,14 @@ export function checkLicenseExpired(Private, Promise, kbnBaseUrl, kbnUrl) { export function getLicenseHasExpired() { return licenseHasExpired; } + +export function xpackFeatureProvider(Private) { + const xpackInfo = Private(XPackInfoProvider); + function isAvailable(feature) { + return xpackInfo.get(`features.${feature}.isAvailable`, false); + } + + return { + isAvailable + }; +} diff --git a/x-pack/plugins/ml/public/register_feature.js b/x-pack/plugins/ml/public/register_feature.js index d1a618c5a17dcb..131d392bd35a87 100644 --- a/x-pack/plugins/ml/public/register_feature.js +++ b/x-pack/plugins/ml/public/register_feature.js @@ -13,7 +13,7 @@ FeatureCatalogueRegistryProvider.register(() => { id: 'ml', title: 'Machine Learning', description: 'Automatically model the normal behavior of your time series data to detect anomalies.', - icon: '/plugins/ml/assets/app_ml.svg', + icon: 'machineLearningApp', path: '/app/ml', showOnHomePage: true, category: FeatureCatalogueCategory.DATA diff --git a/x-pack/plugins/ml/public/services/calendar_service.js b/x-pack/plugins/ml/public/services/calendar_service.js index ba7e9926e1f791..11e0e39527b2df 100644 --- a/x-pack/plugins/ml/public/services/calendar_service.js +++ b/x-pack/plugins/ml/public/services/calendar_service.js @@ -9,92 +9,86 @@ import _ from 'lodash'; import { ml } from 'plugins/ml/services/ml_api_service'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; -let calendarService = undefined; -export function CalendarServiceProvider($q, Private) { - const msgs = mlMessageBarService; - const mlJobService = Private(JobServiceProvider); - class CalendarService { - constructor() { - this.calendars = []; - // list of calendar ids per job id - this.jobCalendars = {}; - // list of calendar ids per group id - this.groupCalendars = {}; - } +const msgs = mlMessageBarService; - loadCalendars(jobs) { - return $q((resolve, reject) => { - let calendars = []; - jobs.forEach((j) => { - this.jobCalendars[j.job_id] = []; - }); - const groups = {}; - mlJobService.getJobGroups().forEach((g) => { - groups[g.id] = g; - }); +class CalendarService { + constructor() { + this.calendars = []; + // list of calendar ids per job id + this.jobCalendars = {}; + // list of calendar ids per group id + this.groupCalendars = {}; + } - ml.calendars() - .then((resp) => { - calendars = resp; - // loop through calendars and their job_ids and create jobCalendars - // if a group is found, expand it out to its member jobs - calendars.forEach((cal) => { - cal.job_ids.forEach((id) => { - let isGroup = false; - // the job_id could be either a job id or a group id - if (this.jobCalendars[id] !== undefined) { - this.jobCalendars[id].push(cal.calendar_id); - } else if (groups[id] !== undefined) { - isGroup = true; - // expand out the group into its jobs and add each job - groups[id].jobs.forEach((j) => { - this.jobCalendars[j.job_id].push(cal.calendar_id); - }); - } else { - // not a known job or a known group. assume it's a unused group - isGroup = true; - } + loadCalendars(jobs) { + return new Promise((resolve, reject) => { + let calendars = []; + jobs.forEach((j) => { + this.jobCalendars[j.job_id] = []; + }); + const groups = {}; + mlJobService.getJobGroups().forEach((g) => { + groups[g.id] = g; + }); - if (isGroup) { - // keep track of calendars per group - if (this.groupCalendars[id] === undefined) { - this.groupCalendars[id] = [cal.calendar_id]; - } else { - this.groupCalendars[id].push(cal.calendar_id); - } - } - }); - }); + ml.calendars() + .then((resp) => { + calendars = resp; + // loop through calendars and their job_ids and create jobCalendars + // if a group is found, expand it out to its member jobs + calendars.forEach((cal) => { + cal.job_ids.forEach((id) => { + let isGroup = false; + // the job_id could be either a job id or a group id + if (this.jobCalendars[id] !== undefined) { + this.jobCalendars[id].push(cal.calendar_id); + } else if (groups[id] !== undefined) { + isGroup = true; + // expand out the group into its jobs and add each job + groups[id].jobs.forEach((j) => { + this.jobCalendars[j.job_id].push(cal.calendar_id); + }); + } else { + // not a known job or a known group. assume it's a unused group + isGroup = true; + } - // deduplicate as group expansion may have added dupes. - _.each(this.jobCalendars, (cal, id) => { - this.jobCalendars[id] = _.uniq(cal); + if (isGroup) { + // keep track of calendars per group + if (this.groupCalendars[id] === undefined) { + this.groupCalendars[id] = [cal.calendar_id]; + } else { + this.groupCalendars[id].push(cal.calendar_id); + } + } }); + }); - this.calendars = calendars; - resolve({ calendars }); - }) - .catch((err) => { - msgs.error('Calendars list could not be retrieved'); - msgs.error('', err); - reject({ calendars, err }); + // deduplicate as group expansion may have added dupes. + _.each(this.jobCalendars, (cal, id) => { + this.jobCalendars[id] = _.uniq(cal); }); - }); - } - // get the list of calendar groups - getCalendarGroups() { - return Object.keys(this.groupCalendars).map(id => ({ id })); - } + this.calendars = calendars; + resolve({ calendars }); + }) + .catch((err) => { + msgs.error('Calendars list could not be retrieved'); + msgs.error('', err); + reject({ calendars, err }); + }); + }); } - if (calendarService === undefined) { - calendarService = new CalendarService(); + // get the list of calendar groups + getCalendarGroups() { + return Object.keys(this.groupCalendars).map(id => ({ id })); } - return calendarService; } + +export const mlCalendarService = new CalendarService(); diff --git a/x-pack/plugins/ml/public/services/field_format_service.js b/x-pack/plugins/ml/public/services/field_format_service.js index b70b8f200037ed..c02160c15a9fd7 100644 --- a/x-pack/plugins/ml/public/services/field_format_service.js +++ b/x-pack/plugins/ml/public/services/field_format_service.js @@ -8,125 +8,117 @@ import _ from 'lodash'; -import 'ui/courier'; import { mlFunctionToESAggregation } from 'plugins/ml/../common/util/job_utils'; -import { getIndexPatternProvider } from 'plugins/ml/util/index_utils'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; +import { getIndexPatternById } from 'plugins/ml/util/index_utils'; +import { mlJobService } from 'plugins/ml/services/job_service'; // Service for accessing FieldFormat objects configured for a Kibana index pattern // for use in formatting the actual and typical values from anomalies. -export function FieldFormatServiceProvider( - $q, - courier, - Private) { - const mlJobService = Private(JobServiceProvider); - const getIndexPattern = Private(getIndexPatternProvider); - - class FieldFormatService { - constructor() { - this.indexPatternIdsByJob = {}; - this.formatsByJob = {}; - } +class FieldFormatService { + constructor() { + this.indexPatternIdsByJob = {}; + this.formatsByJob = {}; + } - // Populate the service with the FieldFormats for the list of jobs with the - // specified IDs. List of Kibana index patterns is passed, with a title - // attribute set in each pattern which will be compared to the index pattern - // configured in the datafeed of each job. - // Builds a map of Kibana FieldFormats (ui/field_formats/field_format.js) - // against detector index by job ID. - populateFormats(jobIds, indexPatterns) { - return $q((resolve, reject) => { - // Populate a map of index pattern IDs against job ID, by finding the ID of the index - // pattern with a title attribute which matches the index configured in the datafeed. - // If a Kibana index pattern has not been created - // for this index, then no custom field formatting will occur. - _.each(jobIds, (jobId) => { - const jobObj = mlJobService.getJob(jobId); - const datafeedIndices = jobObj.datafeed_config.indices; - const indexPattern = _.find(indexPatterns, (index) => { - return _.find(datafeedIndices, (datafeedIndex) => { - return index.get('title') === datafeedIndex; - }); + // Populate the service with the FieldFormats for the list of jobs with the + // specified IDs. List of Kibana index patterns is passed, with a title + // attribute set in each pattern which will be compared to the index pattern + // configured in the datafeed of each job. + // Builds a map of Kibana FieldFormats (ui/field_formats/field_format.js) + // against detector index by job ID. + populateFormats(jobIds, indexPatterns) { + return new Promise((resolve, reject) => { + // Populate a map of index pattern IDs against job ID, by finding the ID of the index + // pattern with a title attribute which matches the index configured in the datafeed. + // If a Kibana index pattern has not been created + // for this index, then no custom field formatting will occur. + _.each(jobIds, (jobId) => { + const jobObj = mlJobService.getJob(jobId); + const datafeedIndices = jobObj.datafeed_config.indices; + const indexPattern = _.find(indexPatterns, (index) => { + return _.find(datafeedIndices, (datafeedIndex) => { + return index.get('title') === datafeedIndex; }); - - // Check if index pattern has been configured to match the index in datafeed. - if (indexPattern !== undefined) { - this.indexPatternIdsByJob[jobId] = indexPattern.id; - } }); - const promises = jobIds.map(jobId => $q.all([ - this.getFormatsForJob(jobId) - ])); + // Check if index pattern has been configured to match the index in datafeed. + if (indexPattern !== undefined) { + this.indexPatternIdsByJob[jobId] = indexPattern.id; + } + }); - $q.all(promises).then((fmtsByJobByDetector) => { - _.each(fmtsByJobByDetector, (formatsByDetector, index) => { - this.formatsByJob[jobIds[index]] = formatsByDetector[0]; - }); + const promises = jobIds.map(jobId => Promise.all([ + this.getFormatsForJob(jobId) + ])); - resolve(this.formatsByJob); - }).catch(err => { - console.log('fieldFormatService error populating formats:', err); - reject({ formats: {}, err }); + Promise.all(promises).then((fmtsByJobByDetector) => { + _.each(fmtsByJobByDetector, (formatsByDetector, index) => { + this.formatsByJob[jobIds[index]] = formatsByDetector[0]; }); + resolve(this.formatsByJob); + }).catch(err => { + console.log('fieldFormatService error populating formats:', err); + reject({ formats: {}, err }); }); - } - // Return the FieldFormat to use for formatting values from - // the detector from the job with the specified ID. - getFieldFormat(jobId, detectorIndex) { - return _.get(this.formatsByJob, [jobId, detectorIndex]); - } + }); + } + // Return the FieldFormat to use for formatting values from + // the detector from the job with the specified ID. + getFieldFormat(jobId, detectorIndex) { + return _.get(this.formatsByJob, [jobId, detectorIndex]); + } - // Utility for returning the FieldFormat from a full populated Kibana index pattern object - // containing the list of fields by name with their formats. - getFieldFormatFromIndexPattern(fullIndexPattern, fieldName, esAggName) { - // Don't use the field formatter for distinct count detectors as - // e.g. distinct_count(clientip) should be formatted as a count, not as an IP address. - let fieldFormat = undefined; - if (esAggName !== 'cardinality') { - const indexPatternFields = _.get(fullIndexPattern, 'fields.byName', []); - fieldFormat = _.get(indexPatternFields, [fieldName, 'format']); - } - return fieldFormat; + // Utility for returning the FieldFormat from a full populated Kibana index pattern object + // containing the list of fields by name with their formats. + getFieldFormatFromIndexPattern(fullIndexPattern, fieldName, esAggName) { + // Don't use the field formatter for distinct count detectors as + // e.g. distinct_count(clientip) should be formatted as a count, not as an IP address. + let fieldFormat = undefined; + if (esAggName !== 'cardinality') { + const indexPatternFields = _.get(fullIndexPattern, 'fields.byName', []); + fieldFormat = _.get(indexPatternFields, [fieldName, 'format']); } - getFormatsForJob(jobId) { - return $q((resolve, reject) => { + return fieldFormat; + } - const jobObj = mlJobService.getJob(jobId); - const detectors = jobObj.analysis_config.detectors || []; - const formatsByDetector = {}; - - const indexPatternId = this.indexPatternIdsByJob[jobId]; - if (indexPatternId !== undefined) { - // Load the full index pattern configuration to obtain the formats of each field. - getIndexPattern(indexPatternId) - .then((indexPatternData) => { - // Store the FieldFormat for each job by detector_index. - const fieldsByName = _.get(indexPatternData, 'fields.byName', []); - _.each(detectors, (dtr) => { - const esAgg = mlFunctionToESAggregation(dtr.function); - // distinct_count detectors should fall back to the default - // formatter as the values are just counts. - if (dtr.field_name !== undefined && esAgg !== 'cardinality') { - formatsByDetector[dtr.detector_index] = _.get(fieldsByName, [dtr.field_name, 'format']); - } - }); - - resolve(formatsByDetector); - }).catch(err => { - reject(err); + getFormatsForJob(jobId) { + return new Promise((resolve, reject) => { + + const jobObj = mlJobService.getJob(jobId); + const detectors = jobObj.analysis_config.detectors || []; + const formatsByDetector = {}; + + const indexPatternId = this.indexPatternIdsByJob[jobId]; + if (indexPatternId !== undefined) { + // Load the full index pattern configuration to obtain the formats of each field. + getIndexPatternById(indexPatternId) + .then((indexPatternData) => { + // Store the FieldFormat for each job by detector_index. + const fieldsByName = _.get(indexPatternData, 'fields.byName', []); + _.each(detectors, (dtr) => { + const esAgg = mlFunctionToESAggregation(dtr.function); + // distinct_count detectors should fall back to the default + // formatter as the values are just counts. + if (dtr.field_name !== undefined && esAgg !== 'cardinality') { + formatsByDetector[dtr.detector_index] = _.get(fieldsByName, [dtr.field_name, 'format']); + } }); - } else { - resolve(formatsByDetector); - } - }); - } - } - return new FieldFormatService(); + resolve(formatsByDetector); + }).catch(err => { + reject(err); + }); + } else { + resolve(formatsByDetector); + } + }); + } } + +export const mlFieldFormatService = new FieldFormatService(); + diff --git a/x-pack/plugins/ml/public/services/forecast_service.js b/x-pack/plugins/ml/public/services/forecast_service.js index d07de1911f754e..09a6b03f4658a0 100644 --- a/x-pack/plugins/ml/public/services/forecast_service.js +++ b/x-pack/plugins/ml/public/services/forecast_service.js @@ -10,375 +10,374 @@ // data on forecasts that have been performed. import _ from 'lodash'; -import { ML_RESULTS_INDEX_PATTERN } from 'plugins/ml/constants/index_patterns'; +import { ML_RESULTS_INDEX_PATTERN } from 'plugins/ml/../common/constants/index_patterns'; import { ml } from 'plugins/ml/services/ml_api_service'; -export function ForecastServiceProvider(es, $q) { - - // Gets a basic summary of the most recently run forecasts for the specified - // job, with results at or later than the supplied timestamp. - // Extra query object can be supplied, or pass null if no additional query. - // Returned response contains a forecasts property, which is an array of objects - // containing id, earliest and latest keys. - function getForecastsSummary( - job, - query, - earliestMs, - maxResults - ) { - return $q((resolve, reject) => { - const obj = { - success: true, - forecasts: [] - }; - // Build the criteria to use in the bool filter part of the request. - // Add criteria for the job ID, result type and earliest time, plus - // the additional query if supplied. - const filterCriteria = [ - { - term: { result_type: 'model_forecast_request_stats' } - }, - { - term: { job_id: job.job_id } - }, - { - range: { - timestamp: { - gte: earliestMs, - format: 'epoch_millis' - } + +// Gets a basic summary of the most recently run forecasts for the specified +// job, with results at or later than the supplied timestamp. +// Extra query object can be supplied, or pass null if no additional query. +// Returned response contains a forecasts property, which is an array of objects +// containing id, earliest and latest keys. +function getForecastsSummary( + job, + query, + earliestMs, + maxResults +) { + return new Promise((resolve, reject) => { + const obj = { + success: true, + forecasts: [] + }; + + // Build the criteria to use in the bool filter part of the request. + // Add criteria for the job ID, result type and earliest time, plus + // the additional query if supplied. + const filterCriteria = [ + { + term: { result_type: 'model_forecast_request_stats' } + }, + { + term: { job_id: job.job_id } + }, + { + range: { + timestamp: { + gte: earliestMs, + format: 'epoch_millis' } } - ]; - - if (query) { - filterCriteria.push(query); } + ]; - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: maxResults, - body: { - query: { - bool: { - filter: filterCriteria - } - }, - sort: [ - { forecast_create_timestamp: { 'order': 'desc' } } - ] - } - }) - .then((resp) => { - if (resp.hits.total !== 0) { - obj.forecasts = resp.hits.hits.map(hit => hit._source); - } + if (query) { + filterCriteria.push(query); + } - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); - }); - } + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: maxResults, + body: { + query: { + bool: { + filter: filterCriteria + } + }, + sort: [ + { forecast_create_timestamp: { 'order': 'desc' } } + ] + } + }) + .then((resp) => { + if (resp.hits.total !== 0) { + obj.forecasts = resp.hits.hits.map(hit => hit._source); + } - // Obtains the earliest and latest timestamps for the forecast data from - // the forecast with the specified ID. - // Returned response contains earliest and latest properties which are the - // timestamps of the first and last model_forecast results. - function getForecastDateRange(job, forecastId) { - - return $q((resolve, reject) => { - const obj = { - success: true, - earliest: null, - latest: null - }; + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); +} - // Build the criteria to use in the bool filter part of the request. - // Add criteria for the job ID, forecast ID, result type and time range. - const filterCriteria = [{ - query_string: { - query: 'result_type:model_forecast', - analyze_wildcard: true - } - }, - { - term: { job_id: job.job_id } - }, - { - term: { forecast_id: forecastId } - }]; - - // TODO - add in criteria for detector index and entity fields (by, over, partition) - // once forecasting with these parameters is supported. - - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: filterCriteria +// Obtains the earliest and latest timestamps for the forecast data from +// the forecast with the specified ID. +// Returned response contains earliest and latest properties which are the +// timestamps of the first and last model_forecast results. +function getForecastDateRange(job, forecastId) { + + return new Promise((resolve, reject) => { + const obj = { + success: true, + earliest: null, + latest: null + }; + + // Build the criteria to use in the bool filter part of the request. + // Add criteria for the job ID, forecast ID, result type and time range. + const filterCriteria = [{ + query_string: { + query: 'result_type:model_forecast', + analyze_wildcard: true + } + }, + { + term: { job_id: job.job_id } + }, + { + term: { forecast_id: forecastId } + }]; + + // TODO - add in criteria for detector index and entity fields (by, over, partition) + // once forecasting with these parameters is supported. + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: filterCriteria + } + }, + aggs: { + earliest: { + min: { + field: 'timestamp' } }, - aggs: { - earliest: { - min: { - field: 'timestamp' - } - }, - latest: { - max: { - field: 'timestamp' - } + latest: { + max: { + field: 'timestamp' } } } - }) - .then((resp) => { - obj.earliest = _.get(resp, 'aggregations.earliest.value', null); - obj.latest = _.get(resp, 'aggregations.latest.value', null); - if (obj.earliest === null || obj.latest === null) { - reject(resp); - } else { - resolve(obj); - } - }) - .catch((resp) => { + } + }) + .then((resp) => { + obj.earliest = _.get(resp, 'aggregations.earliest.value', null); + obj.latest = _.get(resp, 'aggregations.latest.value', null); + if (obj.earliest === null || obj.latest === null) { reject(resp); - }); + } else { + resolve(obj); + } + }) + .catch((resp) => { + reject(resp); + }); - }); - } + }); +} - // Obtains the requested forecast model data for the forecast with the specified ID. - function getForecastData( - job, - detectorIndex, - forecastId, - entityFields, - earliestMs, - latestMs, - interval, - aggType) { - // Extract the partition, by, over fields on which to filter. - const criteriaFields = []; - const detector = job.analysis_config.detectors[detectorIndex]; - if (_.has(detector, 'partition_field_name')) { - const partitionEntity = _.find(entityFields, { 'fieldName': detector.partition_field_name }); - if (partitionEntity !== undefined) { - criteriaFields.push( - { fieldName: 'partition_field_name', fieldValue: partitionEntity.fieldName }, - { fieldName: 'partition_field_value', fieldValue: partitionEntity.fieldValue }); - } +// Obtains the requested forecast model data for the forecast with the specified ID. +function getForecastData( + job, + detectorIndex, + forecastId, + entityFields, + earliestMs, + latestMs, + interval, + aggType) { + // Extract the partition, by, over fields on which to filter. + const criteriaFields = []; + const detector = job.analysis_config.detectors[detectorIndex]; + if (_.has(detector, 'partition_field_name')) { + const partitionEntity = _.find(entityFields, { 'fieldName': detector.partition_field_name }); + if (partitionEntity !== undefined) { + criteriaFields.push( + { fieldName: 'partition_field_name', fieldValue: partitionEntity.fieldName }, + { fieldName: 'partition_field_value', fieldValue: partitionEntity.fieldValue }); } + } - if (_.has(detector, 'over_field_name')) { - const overEntity = _.find(entityFields, { 'fieldName': detector.over_field_name }); - if (overEntity !== undefined) { - criteriaFields.push( - { fieldName: 'over_field_name', fieldValue: overEntity.fieldName }, - { fieldName: 'over_field_value', fieldValue: overEntity.fieldValue }); - } + if (_.has(detector, 'over_field_name')) { + const overEntity = _.find(entityFields, { 'fieldName': detector.over_field_name }); + if (overEntity !== undefined) { + criteriaFields.push( + { fieldName: 'over_field_name', fieldValue: overEntity.fieldName }, + { fieldName: 'over_field_value', fieldValue: overEntity.fieldValue }); } + } - if (_.has(detector, 'by_field_name')) { - const byEntity = _.find(entityFields, { 'fieldName': detector.by_field_name }); - if (byEntity !== undefined) { - criteriaFields.push( - { fieldName: 'by_field_name', fieldValue: byEntity.fieldName }, - { fieldName: 'by_field_value', fieldValue: byEntity.fieldValue }); - } + if (_.has(detector, 'by_field_name')) { + const byEntity = _.find(entityFields, { 'fieldName': detector.by_field_name }); + if (byEntity !== undefined) { + criteriaFields.push( + { fieldName: 'by_field_name', fieldValue: byEntity.fieldName }, + { fieldName: 'by_field_value', fieldValue: byEntity.fieldValue }); } + } - return $q((resolve, reject) => { - const obj = { - success: true, - results: {} - }; - - // Build the criteria to use in the bool filter part of the request. - // Add criteria for the job ID, forecast ID, detector index, result type and time range. - const filterCriteria = [{ - query_string: { - query: 'result_type:model_forecast', - analyze_wildcard: true - } - }, - { - term: { job_id: job.job_id } - }, - { - term: { forecast_id: forecastId } - }, - { - term: { detector_index: detectorIndex } - }, - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } + return new Promise((resolve, reject) => { + const obj = { + success: true, + results: {} + }; + + // Build the criteria to use in the bool filter part of the request. + // Add criteria for the job ID, forecast ID, detector index, result type and time range. + const filterCriteria = [{ + query_string: { + query: 'result_type:model_forecast', + analyze_wildcard: true + } + }, + { + term: { job_id: job.job_id } + }, + { + term: { forecast_id: forecastId } + }, + { + term: { detector_index: detectorIndex } + }, + { + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' } - }]; + } + }]; - // Add in term queries for each of the specified criteria. - _.each(criteriaFields, (criteria) => { - filterCriteria.push({ - term: { - [criteria.fieldName]: criteria.fieldValue - } - }); + // Add in term queries for each of the specified criteria. + _.each(criteriaFields, (criteria) => { + filterCriteria.push({ + term: { + [criteria.fieldName]: criteria.fieldValue + } }); + }); - // If an aggType object has been passed in, use it. - // Otherwise default to avg, min and max aggs for the - // forecast prediction, upper and lower - const forecastAggs = (aggType === undefined) ? - { avg: 'avg', max: 'max', min: 'min' } : - { - avg: aggType.avg, - max: aggType.max, - min: aggType.min - }; - - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: filterCriteria - } - }, - aggs: { - times: { - date_histogram: { - field: 'timestamp', - interval: interval, - min_doc_count: 1 + // If an aggType object has been passed in, use it. + // Otherwise default to avg, min and max aggs for the + // forecast prediction, upper and lower + const forecastAggs = (aggType === undefined) ? + { avg: 'avg', max: 'max', min: 'min' } : + { + avg: aggType.avg, + max: aggType.max, + min: aggType.min + }; + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: filterCriteria + } + }, + aggs: { + times: { + date_histogram: { + field: 'timestamp', + interval: interval, + min_doc_count: 1 + }, + aggs: { + prediction: { + [forecastAggs.avg]: { + field: 'forecast_prediction' + } + }, + forecastUpper: { + [forecastAggs.max]: { + field: 'forecast_upper' + } }, - aggs: { - prediction: { - [forecastAggs.avg]: { - field: 'forecast_prediction' - } - }, - forecastUpper: { - [forecastAggs.max]: { - field: 'forecast_upper' - } - }, - forecastLower: { - [forecastAggs.min]: { - field: 'forecast_lower' - } + forecastLower: { + [forecastAggs.min]: { + field: 'forecast_lower' } } } } } - }) - .then((resp) => { - const aggregationsByTime = _.get(resp, ['aggregations', 'times', 'buckets'], []); - _.each(aggregationsByTime, (dataForTime) => { - const time = dataForTime.key; - obj.results[time] = { - prediction: _.get(dataForTime, ['prediction', 'value']), - forecastUpper: _.get(dataForTime, ['forecastUpper', 'value']), - forecastLower: _.get(dataForTime, ['forecastLower', 'value']) - }; - }); - - resolve(obj); - }) - .catch((resp) => { - reject(resp); + } + }) + .then((resp) => { + const aggregationsByTime = _.get(resp, ['aggregations', 'times', 'buckets'], []); + _.each(aggregationsByTime, (dataForTime) => { + const time = dataForTime.key; + obj.results[time] = { + prediction: _.get(dataForTime, ['prediction', 'value']), + forecastUpper: _.get(dataForTime, ['forecastUpper', 'value']), + forecastLower: _.get(dataForTime, ['forecastLower', 'value']) + }; }); - }); - } - - // Runs a forecast - function runForecast(jobId, duration) { - console.log('ML forecast service run forecast with duration:', duration); - return $q((resolve, reject) => { - - ml.forecast({ - jobId, - duration + resolve(obj); }) - .then((resp) => { - resolve(resp); - }).catch((err) => { - reject(err); - }); - }); - } + .catch((resp) => { + reject(resp); + }); - // Gets stats for a forecast that has been run on the specified job. - // Returned response contains a stats property, including - // forecast_progress (a value from 0 to 1), - // and forecast_status ('finished' when complete) properties. - function getForecastRequestStats(job, forecastId) { - return $q((resolve, reject) => { - const obj = { - success: true, - stats: {} - }; + }); +} - // Build the criteria to use in the bool filter part of the request. - // Add criteria for the job ID, result type and earliest time. - const filterCriteria = [{ - query_string: { - query: 'result_type:model_forecast_request_stats', - analyze_wildcard: true - } - }, - { - term: { job_id: job.job_id } - }, - { - term: { forecast_id: forecastId } - }]; - - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 1, - body: { - query: { - bool: { - filter: filterCriteria - } +// Runs a forecast +function runForecast(jobId, duration) { + console.log('ML forecast service run forecast with duration:', duration); + return new Promise((resolve, reject) => { + + ml.forecast({ + jobId, + duration + }) + .then((resp) => { + resolve(resp); + }).catch((err) => { + reject(err); + }); + }); +} + +// Gets stats for a forecast that has been run on the specified job. +// Returned response contains a stats property, including +// forecast_progress (a value from 0 to 1), +// and forecast_status ('finished' when complete) properties. +function getForecastRequestStats(job, forecastId) { + return new Promise((resolve, reject) => { + const obj = { + success: true, + stats: {} + }; + + // Build the criteria to use in the bool filter part of the request. + // Add criteria for the job ID, result type and earliest time. + const filterCriteria = [{ + query_string: { + query: 'result_type:model_forecast_request_stats', + analyze_wildcard: true + } + }, + { + term: { job_id: job.job_id } + }, + { + term: { forecast_id: forecastId } + }]; + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 1, + body: { + query: { + bool: { + filter: filterCriteria } } + } + }) + .then((resp) => { + if (resp.hits.total !== 0) { + obj.stats = _.first(resp.hits.hits)._source; + } + resolve(obj); }) - .then((resp) => { - if (resp.hits.total !== 0) { - obj.stats = _.first(resp.hits.hits)._source; - } - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); + .catch((resp) => { + reject(resp); + }); - }); - } + }); +} - return { - getForecastsSummary, - getForecastDateRange, - getForecastData, - runForecast, - getForecastRequestStats - }; +export const mlForecastService = { + getForecastsSummary, + getForecastDateRange, + getForecastData, + runForecast, + getForecastRequestStats +}; -} diff --git a/x-pack/plugins/ml/public/services/http_service.js b/x-pack/plugins/ml/public/services/http_service.js index e368ad5a768b10..5a7e4d9c1d70f2 100644 --- a/x-pack/plugins/ml/public/services/http_service.js +++ b/x-pack/plugins/ml/public/services/http_service.js @@ -27,14 +27,19 @@ export function http(options) { const allHeaders = (options.headers === undefined) ? headers : { ...options.headers, ...headers }; const body = (options.data === undefined) ? null : JSON.stringify(options.data); - fetch(url, { + const payload = { method: (options.method || 'GET'), - headers: (allHeaders), - credentials: 'same-origin', - body, - }) + headers: allHeaders, + credentials: 'same-origin' + }; + + if (body !== null) { + payload.body = body; + } + + fetch(url, payload) .then((resp) => { - resolve(resp.json()); + resp.json().then((resp.ok === true) ? resolve : reject); }) .catch((resp) => { reject(resp); diff --git a/x-pack/plugins/ml/public/services/job_messages_service.js b/x-pack/plugins/ml/public/services/job_messages_service.js index ab34faeb0d4d05..dd2481886d4fd4 100644 --- a/x-pack/plugins/ml/public/services/job_messages_service.js +++ b/x-pack/plugins/ml/public/services/job_messages_service.js @@ -10,132 +10,131 @@ // Service for carrying out Elasticsearch queries to obtain data for the // Ml Results dashboards. -import { ML_NOTIFICATION_INDEX_PATTERN } from 'plugins/ml/constants/index_patterns'; +import { ML_NOTIFICATION_INDEX_PATTERN } from 'plugins/ml/../common/constants/index_patterns'; +import { ml } from 'plugins/ml/services/ml_api_service'; -export function JobMessagesServiceProvider(es, $q) { - // search for audit messages, jobId is optional. - // without it, all jobs will be listed. - // fromRange should be a string formatted in ES time units. e.g. 12h, 1d, 7d - function getJobAuditMessages(fromRange, jobId) { - return $q((resolve, reject) => { - let jobFilter = {}; - // if no jobId specified, load all of the messages - if (jobId !== undefined) { - jobFilter = { - bool: { - should: [ - { - term: { - job_id: '' // catch system messages - } - }, - { - term: { - job_id: jobId // messages for specified jobId - } +// search for audit messages, jobId is optional. +// without it, all jobs will be listed. +// fromRange should be a string formatted in ES time units. e.g. 12h, 1d, 7d +function getJobAuditMessages(fromRange, jobId) { + return new Promise((resolve, reject) => { + let jobFilter = {}; + // if no jobId specified, load all of the messages + if (jobId !== undefined) { + jobFilter = { + bool: { + should: [ + { + term: { + job_id: '' // catch system messages + } + }, + { + term: { + job_id: jobId // messages for specified jobId } - ] - } - }; - } - - let timeFilter = {}; - if (fromRange !== undefined && fromRange !== '') { - timeFilter = { - range: { - timestamp: { - gte: `now-${fromRange}`, - lte: 'now' } + ] + } + }; + } + + let timeFilter = {}; + if (fromRange !== undefined && fromRange !== '') { + timeFilter = { + range: { + timestamp: { + gte: `now-${fromRange}`, + lte: 'now' } - }; - } + } + }; + } - es.search({ - index: ML_NOTIFICATION_INDEX_PATTERN, - ignore_unavailable: true, - size: 1000, - body: - { - sort: [ - { timestamp: { order: 'asc' } }, - { job_id: { order: 'asc' } } - ], - query: { - bool: { - filter: [ - { - bool: { - must_not: { - term: { - level: 'activity' - } + ml.esSearch({ + index: ML_NOTIFICATION_INDEX_PATTERN, + ignore_unavailable: true, + size: 1000, + body: + { + sort: [ + { timestamp: { order: 'asc' } }, + { job_id: { order: 'asc' } } + ], + query: { + bool: { + filter: [ + { + bool: { + must_not: { + term: { + level: 'activity' } } - }, - jobFilter, - timeFilter - ] - } + } + }, + jobFilter, + timeFilter + ] } } + } + }) + .then((resp) => { + let messages = []; + if (resp.hits.total !== 0) { + messages = resp.hits.hits.map(hit => hit._source); + } + resolve({ messages }); }) - .then((resp) => { - let messages = []; - if (resp.hits.total !== 0) { - messages = resp.hits.hits.map(hit => hit._source); - } - resolve({ messages }); - }) - .catch((resp) => { - reject(resp); - }); - }); - } + .catch((resp) => { + reject(resp); + }); + }); +} - // search highest, most recent audit messages for all jobs for the last 24hrs. - function getAuditMessagesSummary() { - return $q((resolve, reject) => { - es.search({ - index: ML_NOTIFICATION_INDEX_PATTERN, - ignore_unavailable: true, - size: 0, - body: { - query: { - bool: { - filter: { - range: { - timestamp: { - gte: 'now-1d' - } +// search highest, most recent audit messages for all jobs for the last 24hrs. +function getAuditMessagesSummary() { + return new Promise((resolve, reject) => { + ml.esSearch({ + index: ML_NOTIFICATION_INDEX_PATTERN, + ignore_unavailable: true, + size: 0, + body: { + query: { + bool: { + filter: { + range: { + timestamp: { + gte: 'now-1d' } } } - }, - aggs: { - levelsPerJob: { - terms: { - field: 'job_id', - }, - aggs: { - levels: { - terms: { - field: 'level', - }, - aggs: { - latestMessage: { - terms: { - field: 'message.raw', - size: 1, - order: { - latestMessage: 'desc' - } - }, - aggs: { - latestMessage: { - max: { - field: 'timestamp' - } + } + }, + aggs: { + levelsPerJob: { + terms: { + field: 'job_id', + }, + aggs: { + levels: { + terms: { + field: 'level', + }, + aggs: { + latestMessage: { + terms: { + field: 'message.raw', + size: 1, + order: { + latestMessage: 'desc' + } + }, + aggs: { + latestMessage: { + max: { + field: 'timestamp' } } } @@ -145,26 +144,27 @@ export function JobMessagesServiceProvider(es, $q) { } } } + } + }) + .then((resp) => { + let messagesPerJob = []; + if (resp.hits.total !== 0 && + resp.aggregations && + resp.aggregations.levelsPerJob && + resp.aggregations.levelsPerJob.buckets && + resp.aggregations.levelsPerJob.buckets.length) { + messagesPerJob = resp.aggregations.levelsPerJob.buckets; + } + resolve({ messagesPerJob }); }) - .then((resp) => { - let messagesPerJob = []; - if (resp.hits.total !== 0 && - resp.aggregations && - resp.aggregations.levelsPerJob && - resp.aggregations.levelsPerJob.buckets && - resp.aggregations.levelsPerJob.buckets.length) { - messagesPerJob = resp.aggregations.levelsPerJob.buckets; - } - resolve({ messagesPerJob }); - }) - .catch((resp) => { - reject(resp); - }); - }); - } - - return { - getJobAuditMessages, - getAuditMessagesSummary - }; + .catch((resp) => { + reject(resp); + }); + }); } + +export const jobMessagesService = { + getJobAuditMessages, + getAuditMessagesSummary +}; + diff --git a/x-pack/plugins/ml/public/services/job_service.js b/x-pack/plugins/ml/public/services/job_service.js index 6776bbe7648367..53055094560091 100644 --- a/x-pack/plugins/ml/public/services/job_service.js +++ b/x-pack/plugins/ml/public/services/job_service.js @@ -13,98 +13,169 @@ import moment from 'moment'; import { parseInterval } from 'ui/utils/parse_interval'; import { ml } from 'plugins/ml/services/ml_api_service'; -import { labelDuplicateDetectorDescriptions } from 'plugins/ml/util/anomaly_utils'; +import { labelDuplicateDetectorDescriptions } from 'plugins/ml/../common/util/anomaly_utils'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; import { isWebUrl } from 'plugins/ml/util/string_utils'; import { ML_DATA_PREVIEW_COUNT } from 'plugins/ml/../common/util/job_utils'; -let jobService = undefined; - -export function JobServiceProvider($q, es) { - const msgs = mlMessageBarService; - let jobs = []; - let datafeedIds = {}; - - class JobService { - constructor() { - this.currentJob = undefined; - this.jobs = []; - - // Provide ready access to widely used basic job properties. - // Note these get populated on a call to either loadJobs or getBasicJobInfo. - this.basicJobs = {}; - this.jobDescriptions = {}; - this.detectorsByJob = {}; - this.customUrlsByJob = {}; - this.jobStats = { - activeNodes: { label: 'Active ML Nodes', value: 0, show: true }, - total: { label: 'Total jobs', value: 0, show: true }, - open: { label: 'Open jobs', value: 0, show: true }, - closed: { label: 'Closed jobs', value: 0, show: true }, - failed: { label: 'Failed jobs', value: 0, show: false }, - activeDatafeeds: { label: 'Active datafeeds', value: 0, show: true } - }; - this.jobUrls = {}; - } +const msgs = mlMessageBarService; +let jobs = []; +let datafeedIds = {}; + +class JobService { + constructor() { + this.currentJob = undefined; + this.jobs = []; + + // Provide ready access to widely used basic job properties. + // Note these get populated on a call to either loadJobs or getBasicJobInfo. + this.basicJobs = {}; + this.jobDescriptions = {}; + this.detectorsByJob = {}; + this.customUrlsByJob = {}; + this.jobStats = { + activeNodes: { label: 'Active ML Nodes', value: 0, show: true }, + total: { label: 'Total jobs', value: 0, show: true }, + open: { label: 'Open jobs', value: 0, show: true }, + closed: { label: 'Closed jobs', value: 0, show: true }, + failed: { label: 'Failed jobs', value: 0, show: false }, + activeDatafeeds: { label: 'Active datafeeds', value: 0, show: true } + }; + this.jobUrls = {}; + } - getBlankJob() { - return { - job_id: '', - description: '', - groups: [], - analysis_config: { - bucket_span: '15m', - influencers: [], - detectors: [] - }, - data_description: { - time_field: '', - time_format: '', // 'epoch', - field_delimiter: '', - quote_character: '"', - format: 'delimited' - } - }; - } + getBlankJob() { + return { + job_id: '', + description: '', + groups: [], + analysis_config: { + bucket_span: '15m', + influencers: [], + detectors: [] + }, + data_description: { + time_field: '', + time_format: '', // 'epoch', + field_delimiter: '', + quote_character: '"', + format: 'delimited' + } + }; + } - loadJobs() { - return $q((resolve, reject) => { - jobs = []; - datafeedIds = {}; + loadJobs() { + return new Promise((resolve, reject) => { + jobs = []; + datafeedIds = {}; - ml.jobs() - .then((resp) => { - // make deep copy of jobs - angular.copy(resp.jobs, jobs); + ml.jobs() + .then((resp) => { + // make deep copy of jobs + angular.copy(resp.jobs, jobs); + + // load jobs stats + ml.jobStats() + .then((statsResp) => { + // merge jobs stats into jobs + for (let i = 0; i < jobs.length; i++) { + const job = jobs[i]; + // create empty placeholders for stats and datafeed objects + job.data_counts = {}; + job.model_size_stats = {}; + job.datafeed_config = {}; + + for (let j = 0; j < statsResp.jobs.length; j++) { + if (job.job_id === statsResp.jobs[j].job_id) { + const jobStats = angular.copy(statsResp.jobs[j]); + + job.state = jobStats.state; + job.data_counts = jobStats.data_counts; + job.model_size_stats = jobStats.model_size_stats; + if (jobStats.node) { + job.node = jobStats.node; + } + if (jobStats.open_time) { + job.open_time = jobStats.open_time; + } + } + } + } + this.loadDatafeeds() + .then((datafeedsResp) => { + for (let i = 0; i < jobs.length; i++) { + for (let j = 0; j < datafeedsResp.datafeeds.length; j++) { + if (jobs[i].job_id === datafeedsResp.datafeeds[j].job_id) { + jobs[i].datafeed_config = datafeedsResp.datafeeds[j]; + + datafeedIds[jobs[i].job_id] = datafeedsResp.datafeeds[j].datafeed_id; + } + } + } + processBasicJobInfo(this, jobs); + this.jobs = jobs; + createJobStats(this.jobs, this.jobStats); + createJobUrls(this.jobs, this.jobUrls); + resolve({ jobs: this.jobs }); + }); + }) + .catch((err) => { + error(err); + }); + }).catch((err) => { + error(err); + }); + + function error(err) { + console.log('jobService error getting list of jobs:', err); + msgs.error('Jobs list could not be retrieved'); + msgs.error('', err); + reject({ jobs, err }); + } + }); + } + + refreshJob(jobId) { + return new Promise((resolve, reject) => { + ml.jobs({ jobId }) + .then((resp) => { + console.log('refreshJob query response:', resp); + const newJob = {}; + if (resp.jobs && resp.jobs.length) { + angular.copy(resp.jobs[0], newJob); // load jobs stats - ml.jobStats() + ml.jobStats({ jobId }) .then((statsResp) => { // merge jobs stats into jobs - for (let i = 0; i < jobs.length; i++) { - const job = jobs[i]; - // create empty placeholders for stats and datafeed objects - job.data_counts = {}; - job.model_size_stats = {}; - job.datafeed_config = {}; - - for (let j = 0; j < statsResp.jobs.length; j++) { - if (job.job_id === statsResp.jobs[j].job_id) { - const jobStats = angular.copy(statsResp.jobs[j]); - - job.state = jobStats.state; - job.data_counts = jobStats.data_counts; - job.model_size_stats = jobStats.model_size_stats; - if (jobStats.node) { - job.node = jobStats.node; - } - if (jobStats.open_time) { - job.open_time = jobStats.open_time; - } + for (let j = 0; j < statsResp.jobs.length; j++) { + if (newJob.job_id === statsResp.jobs[j].job_id) { + const statsJob = statsResp.jobs[j]; + newJob.state = statsJob.state; + newJob.data_counts = {}; + newJob.model_size_stats = {}; + angular.copy(statsJob.data_counts, newJob.data_counts); + angular.copy(statsJob.model_size_stats, newJob.model_size_stats); + if (newJob.node) { + angular.copy(statsJob.node, newJob.node); + } + + if (statsJob.open_time) { + newJob.open_time = statsJob.open_time; } } } - this.loadDatafeeds() + + // replace the job in the jobs array + for (let i = 0; i < jobs.length; i++) { + if (jobs[i].job_id === newJob.job_id) { + jobs[i] = newJob; + } + } + + const datafeedId = this.getDatafeedId(jobId); + + this.loadDatafeeds(datafeedId) .then((datafeedsResp) => { for (let i = 0; i < jobs.length; i++) { for (let j = 0; j < datafeedsResp.datafeeds.length; j++) { @@ -115,7 +186,6 @@ export function JobServiceProvider($q, es) { } } } - processBasicJobInfo(this, jobs); this.jobs = jobs; createJobStats(this.jobs, this.jobStats); createJobUrls(this.jobs, this.jobUrls); @@ -125,1039 +195,935 @@ export function JobServiceProvider($q, es) { .catch((err) => { error(err); }); - }).catch((err) => { - error(err); - }); + } + }).catch((err) => { + error(err); + }); - function error(err) { - console.log('jobService error getting list of jobs:', err); - msgs.error('Jobs list could not be retrieved'); - msgs.error('', err); - reject({ jobs, err }); - } - }); - } + function error(err) { + console.log('JobService error getting list of jobs:', err); + msgs.error('Jobs list could not be retrieved'); + msgs.error('', err); + reject({ jobs, err }); + } + }); + } - refreshJob(jobId) { - return $q((resolve, reject) => { - ml.jobs({ jobId }) - .then((resp) => { - console.log('refreshJob query response:', resp); - const newJob = {}; - if (resp.jobs && resp.jobs.length) { - angular.copy(resp.jobs[0], newJob); - - // load jobs stats - ml.jobStats({ jobId }) - .then((statsResp) => { - // merge jobs stats into jobs - for (let j = 0; j < statsResp.jobs.length; j++) { - if (newJob.job_id === statsResp.jobs[j].job_id) { - const statsJob = statsResp.jobs[j]; - newJob.state = statsJob.state; - newJob.data_counts = {}; - newJob.model_size_stats = {}; - angular.copy(statsJob.data_counts, newJob.data_counts); - angular.copy(statsJob.model_size_stats, newJob.model_size_stats); - if (newJob.node) { - angular.copy(statsJob.node, newJob.node); - } + loadDatafeeds(datafeedId) { + return new Promise((resolve, reject) => { + const datafeeds = []; + const sId = (datafeedId !== undefined) ? { datafeed_id: datafeedId } : undefined; - if (statsJob.open_time) { - newJob.open_time = statsJob.open_time; - } - } - } + ml.datafeeds(sId) + .then((resp) => { + // console.log('loadDatafeeds query response:', resp); - // replace the job in the jobs array - for (let i = 0; i < jobs.length; i++) { - if (jobs[i].job_id === newJob.job_id) { - jobs[i] = newJob; - } + // make deep copy of datafeeds + angular.copy(resp.datafeeds, datafeeds); + + // load datafeeds stats + ml.datafeedStats() + .then((statsResp) => { + // merge datafeeds stats into datafeeds + for (let i = 0; i < datafeeds.length; i++) { + const datafeed = datafeeds[i]; + for (let j = 0; j < statsResp.datafeeds.length; j++) { + if (datafeed.datafeed_id === statsResp.datafeeds[j].datafeed_id) { + datafeed.state = statsResp.datafeeds[j].state; } + } + } + resolve({ datafeeds }); + }) + .catch((err) => { + error(err); + }); + }).catch((err) => { + error(err); + }); - const datafeedId = this.getDatafeedId(jobId); + function error(err) { + console.log('loadDatafeeds error getting list of datafeeds:', err); + msgs.error('datafeeds list could not be retrieved'); + msgs.error('', err); + reject({ jobs, err }); + } + }); + } - this.loadDatafeeds(datafeedId) - .then((datafeedsResp) => { - for (let i = 0; i < jobs.length; i++) { - for (let j = 0; j < datafeedsResp.datafeeds.length; j++) { - if (jobs[i].job_id === datafeedsResp.datafeeds[j].job_id) { - jobs[i].datafeed_config = datafeedsResp.datafeeds[j]; + updateSingleJobCounts(jobId) { + return new Promise((resolve, reject) => { + console.log('jobService: update job counts and state for ' + jobId); + ml.jobStats({ jobId }) + .then((resp) => { + console.log('updateSingleJobCounts controller query response:', resp); + if (resp.jobs && resp.jobs.length) { + const newJob = {}; + angular.copy(resp.jobs[0], newJob); - datafeedIds[jobs[i].job_id] = datafeedsResp.datafeeds[j].datafeed_id; - } - } - } - this.jobs = jobs; - createJobStats(this.jobs, this.jobStats); - createJobUrls(this.jobs, this.jobUrls); - resolve({ jobs: this.jobs }); - }); - }) - .catch((err) => { - error(err); - }); + // replace the job in the jobs array + for (let i = 0; i < jobs.length; i++) { + if (jobs[i].job_id === jobId) { + const job = jobs[i]; + job.state = newJob.state; + job.data_counts = newJob.data_counts; + if (newJob.model_size_stats) { + job.model_size_stats = newJob.model_size_stats; + } + if (newJob.node) { + job.node = newJob.node; + } + if (newJob.open_time) { + job.open_time = newJob.open_time; + } + } } - }).catch((err) => { - error(err); - }); - - function error(err) { - console.log('JobService error getting list of jobs:', err); - msgs.error('Jobs list could not be retrieved'); - msgs.error('', err); - reject({ jobs, err }); - } - }); - } - loadDatafeeds(datafeedId) { - return $q((resolve, reject) => { - const datafeeds = []; - const sId = (datafeedId !== undefined) ? { datafeed_id: datafeedId } : undefined; + const datafeedId = this.getDatafeedId(jobId); - ml.datafeeds(sId) - .then((resp) => { - // console.log('loadDatafeeds query response:', resp); - - // make deep copy of datafeeds - angular.copy(resp.datafeeds, datafeeds); + this.loadDatafeeds(datafeedId) + .then((datafeedsResp) => { + for (let i = 0; i < jobs.length; i++) { + for (let j = 0; j < datafeedsResp.datafeeds.length; j++) { + if (jobs[i].job_id === datafeedsResp.datafeeds[j].job_id) { + jobs[i].datafeed_config = datafeedsResp.datafeeds[j]; - // load datafeeds stats - ml.datafeedStats() - .then((statsResp) => { - // merge datafeeds stats into datafeeds - for (let i = 0; i < datafeeds.length; i++) { - const datafeed = datafeeds[i]; - for (let j = 0; j < statsResp.datafeeds.length; j++) { - if (datafeed.datafeed_id === statsResp.datafeeds[j].datafeed_id) { - datafeed.state = statsResp.datafeeds[j].state; + datafeedIds[jobs[i].job_id] = datafeedsResp.datafeeds[j].datafeed_id; } } } - resolve({ datafeeds }); + createJobStats(this.jobs, this.jobStats); + createJobUrls(this.jobs, this.jobUrls); + resolve({ jobs: this.jobs }); }) .catch((err) => { error(err); }); - }).catch((err) => { - error(err); - }); + } else { + resolve({ jobs: this.jobs }); + } - function error(err) { - console.log('loadDatafeeds error getting list of datafeeds:', err); - msgs.error('datafeeds list could not be retrieved'); - msgs.error('', err); - reject({ jobs, err }); - } - }); - } + }).catch((err) => { + error(err); + }); - updateSingleJobCounts(jobId) { - return $q((resolve, reject) => { - console.log('jobService: update job counts and state for ' + jobId); - ml.jobStats({ jobId }) - .then((resp) => { - console.log('updateSingleJobCounts controller query response:', resp); - if (resp.jobs && resp.jobs.length) { - const newJob = {}; - angular.copy(resp.jobs[0], newJob); + function error(err) { + console.log('updateSingleJobCounts error getting job details:', err); + msgs.error('Job details could not be retrieved for ' + jobId); + msgs.error('', err); + reject({ jobs, err }); + } - // replace the job in the jobs array - for (let i = 0; i < jobs.length; i++) { - if (jobs[i].job_id === jobId) { - const job = jobs[i]; - job.state = newJob.state; - job.data_counts = newJob.data_counts; - if (newJob.model_size_stats) { - job.model_size_stats = newJob.model_size_stats; - } - if (newJob.node) { - job.node = newJob.node; - } - if (newJob.open_time) { - job.open_time = newJob.open_time; - } - } - } + }); + } - const datafeedId = this.getDatafeedId(jobId); + updateAllJobStats() { + return new Promise((resolve, reject) => { + console.log('jobService: update all jobs counts and state'); + ml.jobStats().then((resp) => { + console.log('updateAllJobStats controller query response:', resp); + let newJobsAdded = false; + for (let d = 0; d < resp.jobs.length; d++) { + const newJobStats = {}; + let jobExists = false; + angular.copy(resp.jobs[d], newJobStats); + + // update parts of the job + for (let i = 0; i < jobs.length; i++) { + const job = jobs[i]; + if (job.job_id === newJobStats.job_id) { + jobExists = true; + job.state = newJobStats.state; + job.data_counts = newJobStats.data_counts; + if (newJobStats.model_size_stats) { + job.model_size_stats = newJobStats.model_size_stats; + } + if (newJobStats.node) { + job.node = newJobStats.node; + } + if (newJobStats.open_time) { + job.open_time = newJobStats.open_time; + } + } + } - this.loadDatafeeds(datafeedId) - .then((datafeedsResp) => { - for (let i = 0; i < jobs.length; i++) { - for (let j = 0; j < datafeedsResp.datafeeds.length; j++) { - if (jobs[i].job_id === datafeedsResp.datafeeds[j].job_id) { - jobs[i].datafeed_config = datafeedsResp.datafeeds[j]; + // a new job has been added, add it to the list + if (!jobExists) { + // add it to the same index position as it's found in jobs. + jobs.splice(d, 0, newJobStats); + newJobsAdded = true; + } + } - datafeedIds[jobs[i].job_id] = datafeedsResp.datafeeds[j].datafeed_id; - } + // load datafeeds stats + ml.datafeedStats() + .then((datafeedsResp) => { + for (let i = 0; i < jobs.length; i++) { + const datafeed = jobs[i].datafeed_config; + if (datafeed) { + for (let j = 0; j < datafeedsResp.datafeeds.length; j++) { + const newDatafeedStats = {}; + angular.copy(datafeedsResp.datafeeds[j], newDatafeedStats); + + if (datafeed.datafeed_id === newDatafeedStats.datafeed_id) { + datafeed.state = newDatafeedStats.state; + if (newDatafeedStats.node) { + datafeed.node = newDatafeedStats.node; } } - createJobStats(this.jobs, this.jobStats); - createJobUrls(this.jobs, this.jobUrls); - resolve({ jobs: this.jobs }); - }) + } + } + } + this.jobs = jobs; + + // if after adding missing jobs, the retrieved number of jobs still differs from + // the local copy, reload the whole list from scratch. some non-running jobs may have + // been deleted by a different user. + if (newJobsAdded || resp.jobs.length !== jobs.length) { + console.log('updateAllJobStats: number of jobs differs. reloading all jobs'); + this.loadJobs().then(() => { + resolve({ jobs: this.jobs, listChanged: true }); + }) .catch((err) => { error(err); }); } else { - resolve({ jobs: this.jobs }); + createJobStats(this.jobs, this.jobStats); + createJobUrls(this.jobs, this.jobUrls); + resolve({ jobs: this.jobs, listChanged: false }); } - - }).catch((err) => { + }) + .catch((err) => { error(err); }); + }) + .catch((err) => { + error(err); + }); - function error(err) { - console.log('updateSingleJobCounts error getting job details:', err); - msgs.error('Job details could not be retrieved for ' + jobId); - msgs.error('', err); - reject({ jobs, err }); - } + function error(err) { + console.log('updateAllJobStats error getting list job details:', err); + msgs.error('Job details could not be retrieved'); + msgs.error('', err); + reject({ jobs, err }); + } - }); - } + }); + } - updateAllJobStats() { - return $q((resolve, reject) => { - console.log('jobService: update all jobs counts and state'); - ml.jobStats().then((resp) => { - console.log('updateAllJobStats controller query response:', resp); - let newJobsAdded = false; - for (let d = 0; d < resp.jobs.length; d++) { - const newJobStats = {}; - let jobExists = false; - angular.copy(resp.jobs[d], newJobStats); - - // update parts of the job - for (let i = 0; i < jobs.length; i++) { - const job = jobs[i]; - if (job.job_id === newJobStats.job_id) { - jobExists = true; - job.state = newJobStats.state; - job.data_counts = newJobStats.data_counts; - if (newJobStats.model_size_stats) { - job.model_size_stats = newJobStats.model_size_stats; - } - if (newJobStats.node) { - job.node = newJobStats.node; - } - if (newJobStats.open_time) { - job.open_time = newJobStats.open_time; - } - } - } + getRunningJobs() { + const runningJobs = []; + _.each(jobs, (job) => { + if (job.datafeed_config && job.datafeed_config.state === 'started') { + runningJobs.push(job); + } + }); + return runningJobs; + } - // a new job has been added, add it to the list - if (!jobExists) { - // add it to the same index position as it's found in jobs. - jobs.splice(d, 0, newJobStats); - newJobsAdded = true; - } - } + updateSingleJobDatafeedState(jobId) { + return new Promise((resolve, reject) => { - // load datafeeds stats - ml.datafeedStats() - .then((datafeedsResp) => { - for (let i = 0; i < jobs.length; i++) { - const datafeed = jobs[i].datafeed_config; - if (datafeed) { - for (let j = 0; j < datafeedsResp.datafeeds.length; j++) { - const newDatafeedStats = {}; - angular.copy(datafeedsResp.datafeeds[j], newDatafeedStats); + const datafeedId = this.getDatafeedId(jobId); - if (datafeed.datafeed_id === newDatafeedStats.datafeed_id) { - datafeed.state = newDatafeedStats.state; - if (newDatafeedStats.node) { - datafeed.node = newDatafeedStats.node; - } - } - } - } - } - this.jobs = jobs; - - // if after adding missing jobs, the retrieved number of jobs still differs from - // the local copy, reload the whole list from scratch. some non-running jobs may have - // been deleted by a different user. - if (newJobsAdded || resp.jobs.length !== jobs.length) { - console.log('updateAllJobStats: number of jobs differs. reloading all jobs'); - this.loadJobs().then(() => { - resolve({ jobs: this.jobs, listChanged: true }); - }) - .catch((err) => { - error(err); - }); - } else { - createJobStats(this.jobs, this.jobStats); - createJobUrls(this.jobs, this.jobUrls); - resolve({ jobs: this.jobs, listChanged: false }); - } - }) - .catch((err) => { - error(err); - }); + ml.datafeedStats({ datafeedId }) + .then((resp) => { + // console.log('updateSingleJobCounts controller query response:', resp); + const datafeeds = resp.datafeeds; + let state = 'UNKNOWN'; + if (datafeeds && datafeeds.length) { + state = datafeeds[0].state; + } + resolve(state); }) - .catch((err) => { - error(err); - }); - - function error(err) { - console.log('updateAllJobStats error getting list job details:', err); - msgs.error('Job details could not be retrieved'); - msgs.error('', err); - reject({ jobs, err }); - } + .catch((resp) => { + reject(resp); + }); - }); - } + }); + } - getRunningJobs() { - const runningJobs = []; - _.each(jobs, (job) => { - if (job.datafeed_config && job.datafeed_config.state === 'started') { - runningJobs.push(job); - } - }); - return runningJobs; + saveNewJob(job) { + // run then and catch through the same check + function func(resp) { + console.log('Response for job query:', resp); + const success = checkSaveResponse(resp, job); + return { success, job, resp }; } - updateSingleJobDatafeedState(jobId) { - return $q((resolve, reject) => { - - const datafeedId = this.getDatafeedId(jobId); + // return the promise chain + return ml.addJob({ jobId: job.job_id, job }) + .then(func).catch(func); + } - ml.datafeedStats({ datafeedId }) - .then((resp) => { - // console.log('updateSingleJobCounts controller query response:', resp); - const datafeeds = resp.datafeeds; - let state = 'UNKNOWN'; - if (datafeeds && datafeeds.length) { - state = datafeeds[0].state; - } - resolve(state); + deleteJob(job, statusIn) { + return new Promise((resolve, reject) => { + const status = statusIn || { deleteDatafeed: 0, deleteJob: 0, errorMessage: '' }; + + // chain of endpoint calls to delete a job. + // if job is datafeed, stop and delete datafeed first + if (job.datafeed_config && Object.keys(job.datafeed_config).length) { + const datafeedId = this.getDatafeedId(job.job_id); + // stop datafeed + ml.forceDeleteDatafeed({ datafeedId: datafeedId }) + .then(() => { + status.deleteDatafeed = 1; + deleteJob(); }) .catch((resp) => { - reject(resp); + status.deleteDatafeed = -1; + status.deleteJob = -1; + deleteFailed(resp, 'Delete datafeed'); }); - - }); - } - - saveNewJob(job) { - // run then and catch through the same check - function func(resp) { - console.log('Response for job query:', resp); - const success = checkSaveResponse(resp, job); - return { success, job, resp }; + } else { + deleteJob(); } - // return the promise chain - return $q.when(ml.addJob({ jobId: job.job_id, job })) - .then(func).catch(func); - } + function deleteJob() { + ml.forceDeleteJob({ jobId: job.job_id }) + .then(() => { + status.deleteJob = 1; + resolve({ success: true }); + }) + .catch((resp) => { + status.deleteJob = -1; + deleteFailed(resp, 'Delete job'); + }); + } - deleteJob(job, statusIn) { - return $q((resolve, reject) => { - const status = statusIn || { deleteDatafeed: 0, deleteJob: 0, errorMessage: '' }; - - // chain of endpoint calls to delete a job. - // if job is datafeed, stop and delete datafeed first - if (job.datafeed_config && Object.keys(job.datafeed_config).length) { - const datafeedId = this.getDatafeedId(job.job_id); - // stop datafeed - ml.forceDeleteDatafeed({ datafeedId: datafeedId }) - .then(() => { - status.deleteDatafeed = 1; - deleteJob(); - }) - .catch((resp) => { - status.deleteDatafeed = -1; - status.deleteJob = -1; - deleteFailed(resp, 'Delete datafeed'); - }); - } else { - deleteJob(); + function deleteFailed(resp, txt) { + if (resp.statusCode === 500) { + status.errorMessage = txt; } + reject({ success: false }); + } - function deleteJob() { - ml.forceDeleteJob({ jobId: job.job_id }) - .then(() => { - status.deleteJob = 1; - resolve({ success: true }); - }) - .catch((resp) => { - status.deleteJob = -1; - deleteFailed(resp, 'Delete job'); - }); - } + }); + } + + cloneJob(job) { + // create a deep copy of a job object + // also remove items from the job which are set by the server and not needed + // in the future this formatting could be optional + const tempJob = angular.copy(job); + + // remove all of the items which should not be copied + // such as counts, state and times + delete tempJob.state; + delete tempJob.job_version; + delete tempJob.data_counts; + delete tempJob.create_time; + delete tempJob.finished_time; + delete tempJob.last_data_time; + delete tempJob.model_size_stats; + delete tempJob.node; + delete tempJob.average_bucket_processing_time_ms; + delete tempJob.model_snapshot_id; + delete tempJob.open_time; + delete tempJob.established_model_memory; + + delete tempJob.analysis_config.use_per_partition_normalization; + + _.each(tempJob.analysis_config.detectors, (d) => { + delete d.detector_index; + }); - function deleteFailed(resp, txt) { - if (resp.statusCode === 500) { - status.errorMessage = txt; + // remove parts of the datafeed config which should not be copied + if (tempJob.datafeed_config) { + delete tempJob.datafeed_config.datafeed_id; + delete tempJob.datafeed_config.job_id; + delete tempJob.datafeed_config.state; + delete tempJob.datafeed_config.node; + + // remove query_delay if it's between 60s and 120s + // the back-end produces a random value between 60 and 120 and so + // by deleting it, the back-end will produce a new random value + if (tempJob.datafeed_config.query_delay) { + const interval = parseInterval(tempJob.datafeed_config.query_delay); + if (interval !== null) { + const queryDelay = interval.asSeconds(); + if (queryDelay > 60 && queryDelay < 120) { + delete tempJob.datafeed_config.query_delay; } - reject({ success: false }); } + } + } + + return tempJob; + } + updateJob(jobId, job) { + // return the promise chain + return ml.updateJob({ jobId, job }) + .then((resp) => { + console.log('update job', resp); + return { success: true }; + }).catch((err) => { + msgs.error('Could not update job: ' + jobId); + console.log('update job', err); + return { success: false, message: err.message }; }); - } + } - cloneJob(job) { - // create a deep copy of a job object - // also remove items from the job which are set by the server and not needed - // in the future this formatting could be optional - const tempJob = angular.copy(job); - - // remove all of the items which should not be copied - // such as counts, state and times - delete tempJob.state; - delete tempJob.job_version; - delete tempJob.data_counts; - delete tempJob.create_time; - delete tempJob.finished_time; - delete tempJob.last_data_time; - delete tempJob.model_size_stats; - delete tempJob.node; - delete tempJob.average_bucket_processing_time_ms; - delete tempJob.model_snapshot_id; - delete tempJob.open_time; - delete tempJob.established_model_memory; - - delete tempJob.analysis_config.use_per_partition_normalization; - - _.each(tempJob.analysis_config.detectors, (d) => { - delete d.detector_index; + validateJob(obj) { + // return the promise chain + return ml.validateJob(obj) + .then((messages) => { + console.log('validate job', messages); + return { success: true, messages }; + }).catch((err) => { + msgs.error('Job Validation Error: ' + err.message); + console.log('validate job', err); + return { + success: false, + messages: [{ + status: 'error', + text: err.message + }] + }; }); + } - // remove parts of the datafeed config which should not be copied - if (tempJob.datafeed_config) { - delete tempJob.datafeed_config.datafeed_id; - delete tempJob.datafeed_config.job_id; - delete tempJob.datafeed_config.state; - delete tempJob.datafeed_config.node; - - // remove query_delay if it's between 60s and 120s - // the back-end produces a random value between 60 and 120 and so - // by deleting it, the back-end will produce a new random value - if (tempJob.datafeed_config.query_delay) { - const interval = parseInterval(tempJob.datafeed_config.query_delay); - if (interval !== null) { - const queryDelay = interval.asSeconds(); - if (queryDelay > 60 && queryDelay < 120) { - delete tempJob.datafeed_config.query_delay; - } - } - } - } + // find a job based on the id + getJob(jobId) { + const job = _.find(jobs, (j) => { + return j.job_id === jobId; + }); - return tempJob; - } + return job; + } - updateJob(jobId, job) { - // return the promise chain - return $q.when(ml.updateJob({ jobId, job })) + // use elasticsearch to load basic information on jobs, as used by various result + // dashboards in the Ml plugin. Returned response contains a jobs property, + // which is an array of objects containing id, description, bucketSpanSeconds, detectors + // and detectorDescriptions properties, plus a customUrls key if custom URLs + // have been configured for the job. + getBasicJobInfo() { + return new Promise((resolve, reject) => { + const obj = { success: true, jobs: [] }; + + ml.jobs() .then((resp) => { - console.log('update job', resp); - return { success: true }; - }).catch((err) => { - msgs.error('Could not update job: ' + jobId); - console.log('update job', err); - return { success: false, message: err.message }; + if (resp.jobs && resp.jobs.length > 0) { + obj.jobs = processBasicJobInfo(this, resp.jobs); + } + resolve(obj); + }) + .catch((resp) => { + console.log('getBasicJobInfo error getting list of jobs:', resp); + reject(resp); }); - } - validateJob(obj) { - // return the promise chain - return $q.when(ml.validateJob(obj)) - .then((messages) => { - console.log('validate job', messages); - return { success: true, messages }; - }).catch((err) => { - msgs.error('Job Validation Error: ' + err.message); - console.log('validate job', err); - return { - success: false, - messages: [{ - status: 'error', - text: err.message - }] - }; + }); + } + + // Obtains the list of fields by which record level results may be viewed for all + // the jobs that have been created. Essentially this is the list of unique 'by', + // 'over' and 'partition' fields that have been defined across all the detectors for + // a job, although for detectors with both 'by' and 'over' fields, the 'by' field name + // is not returned since this field is not added to the top-level record fields. + // Returned response contains a fieldsByJob property, with job ID keys + // against an array of the field names by which record type results may be viewed + // for that job. + // Contains an addition '*' key which holds an array of the + // unique fields across all jobs. + getJobViewByFields() { + return new Promise((resolve, reject) => { + const obj = { success: true, fieldsByJob: { '*': [] } }; + + ml.jobs() + .then(function (resp) { + if (resp.jobs && resp.jobs.length > 0) { + _.each(resp.jobs, (jobObj) => { + // Add the list of distinct by, over and partition fields for each job. + const fieldsForJob = []; + + const analysisConfig = jobObj.analysis_config; + const detectors = analysisConfig.detectors || []; + _.each(detectors, (detector) => { + if (_.has(detector, 'partition_field_name')) { + fieldsForJob.push(detector.partition_field_name); + } + if (_.has(detector, 'over_field_name')) { + fieldsForJob.push(detector.over_field_name); + } + // For jobs with by and over fields, don't add the 'by' field as this + // field will only be added to the top-level fields for record type results + // if it also an influencer over the bucket. + if (_.has(detector, 'by_field_name') && !(_.has(detector, 'over_field_name'))) { + fieldsForJob.push(detector.by_field_name); + } + }); + + obj.fieldsByJob[jobObj.job_id] = _.uniq(fieldsForJob); + obj.fieldsByJob['*'] = _.union(obj.fieldsByJob['*'], obj.fieldsByJob[jobObj.job_id]); + }); + + // Sort fields alphabetically. + _.each(obj.fieldsByJob, (fields, jobId)=> { + obj.fieldsByJob[jobId] = _.sortBy(fields, (field) => { + return field.toLowerCase(); + }); + }); + } + + resolve(obj); + + }) + .catch((resp) => { + console.log('getJobViewByFields error getting list of viewBy fields:', resp); + reject(resp); }); - } - // find a job based on the id - getJob(jobId) { - const job = _.find(jobs, (j) => { - return j.job_id === jobId; - }); + }); + } - return job; - } + searchPreview(job) { + return new Promise((resolve, reject) => { - // use elasticsearch to load basic information on jobs, as used by various result - // dashboards in the Ml plugin. Returned response contains a jobs property, - // which is an array of objects containing id, description, bucketSpanSeconds, detectors - // and detectorDescriptions properties, plus a customUrls key if custom URLs - // have been configured for the job. - getBasicJobInfo() { - return $q((resolve, reject) => { - const obj = { success: true, jobs: [] }; + if (job.datafeed_config) { - ml.jobs() - .then((resp) => { - if (resp.jobs && resp.jobs.length > 0) { - obj.jobs = processBasicJobInfo(this, resp.jobs); - } - resolve(obj); - }) - .catch((resp) => { - console.log('getBasicJobInfo error getting list of jobs:', resp); - reject(resp); - }); + // if query is set, add it to the search, otherwise use match_all + let query = { 'match_all': {} }; + if (job.datafeed_config.query) { + query = job.datafeed_config.query; + } - }); - } - // Obtains the list of fields by which record level results may be viewed for all - // the jobs that have been created. Essentially this is the list of unique 'by', - // 'over' and 'partition' fields that have been defined across all the detectors for - // a job, although for detectors with both 'by' and 'over' fields, the 'by' field name - // is not returned since this field is not added to the top-level record fields. - // Returned response contains a fieldsByJob property, with job ID keys - // against an array of the field names by which record type results may be viewed - // for that job. - // Contains an addition '*' key which holds an array of the - // unique fields across all jobs. - getJobViewByFields() { - return $q((resolve, reject) => { - const obj = { success: true, fieldsByJob: { '*': [] } }; - - ml.jobs() - .then(function (resp) { - if (resp.jobs && resp.jobs.length > 0) { - _.each(resp.jobs, (jobObj) => { - // Add the list of distinct by, over and partition fields for each job. - const fieldsForJob = []; - - const analysisConfig = jobObj.analysis_config; - const detectors = analysisConfig.detectors || []; - _.each(detectors, (detector) => { - if (_.has(detector, 'partition_field_name')) { - fieldsForJob.push(detector.partition_field_name); + // Get bucket span + // Get first doc time for datafeed + // Create a new query - must user query and must range query. + // Time range 'to' first doc time plus < 10 buckets + + // Do a preliminary search to get the date of the earliest doc matching the + // query in the datafeed. This will be used to apply a time range criteria + // on the datafeed search preview. + // This time filter is required for datafeed searches using aggregations to ensure + // the search does not create too many buckets (default 10000 max_bucket limit), + // but apply it to searches without aggregations too for consistency. + ml.getTimeFieldRange({ + index: job.datafeed_config.indices, + timeFieldName: job.data_description.time_field, + query + }) + .then((timeRange) => { + const bucketSpan = parseInterval(job.analysis_config.bucket_span); + const earliestMs = timeRange.start.epoch; + const latestMs = +timeRange.start.epoch + (10 * bucketSpan.asMilliseconds()); + + const body = { + query: { + bool: { + must: [ + { + range: { + [job.data_description.time_field]: { + gte: earliestMs, + lt: latestMs, + format: 'epoch_millis' + } + } + }, + query + ] + } + } + }; + + // if aggs or aggregations is set, add it to the search + const aggregations = job.datafeed_config.aggs || job.datafeed_config.aggregations; + if (aggregations && Object.keys(aggregations).length) { + body.size = 0; + body.aggregations = aggregations; + + // add script_fields if present + const scriptFields = job.datafeed_config.script_fields; + if (scriptFields && Object.keys(scriptFields).length) { + body.script_fields = scriptFields; + } + + } else { + // if aggregations is not set and retrieveWholeSource is not set, add all of the fields from the job + body.size = ML_DATA_PREVIEW_COUNT; + + // add script_fields if present + const scriptFields = job.datafeed_config.script_fields; + if (scriptFields && Object.keys(scriptFields).length) { + body.script_fields = scriptFields; + } + + const fields = {}; + + // get fields from detectors + if (job.analysis_config.detectors) { + _.each(job.analysis_config.detectors, (dtr) => { + if (dtr.by_field_name) { + fields[dtr.by_field_name] = {}; + } + if (dtr.field_name) { + fields[dtr.field_name] = {}; } - if (_.has(detector, 'over_field_name')) { - fieldsForJob.push(detector.over_field_name); + if (dtr.over_field_name) { + fields[dtr.over_field_name] = {}; } - // For jobs with by and over fields, don't add the 'by' field as this - // field will only be added to the top-level fields for record type results - // if it also an influencer over the bucket. - if (_.has(detector, 'by_field_name') && !(_.has(detector, 'over_field_name'))) { - fieldsForJob.push(detector.by_field_name); + if (dtr.partition_field_name) { + fields[dtr.partition_field_name] = {}; } }); + } - obj.fieldsByJob[jobObj.job_id] = _.uniq(fieldsForJob); - obj.fieldsByJob['*'] = _.union(obj.fieldsByJob['*'], obj.fieldsByJob[jobObj.job_id]); - }); - - // Sort fields alphabetically. - _.each(obj.fieldsByJob, (fields, jobId)=> { - obj.fieldsByJob[jobId] = _.sortBy(fields, (field) => { - return field.toLowerCase(); + // get fields from influencers + if (job.analysis_config.influencers) { + _.each(job.analysis_config.influencers, (inf) => { + fields[inf] = {}; }); - }); - } + } - resolve(obj); + // get fields from categorizationFieldName + if (job.analysis_config.categorization_field_name) { + fields[job.analysis_config.categorization_field_name] = {}; + } - }) - .catch((resp) => { - console.log('getJobViewByFields error getting list of viewBy fields:', resp); - reject(resp); - }); + // get fields from summary_count_field_name + if (job.analysis_config.summary_count_field_name) { + fields[job.analysis_config.summary_count_field_name] = {}; + } - }); - } + // get fields from time_field + if (job.data_description.time_field) { + fields[job.data_description.time_field] = {}; + } - // search to load a few records to extract the time field - searchTimeFields(index, type, field) { - return $q((resolve, reject) => { - const obj = { time: '' }; - - es.search({ - method: 'GET', - index: index, - type: type, - size: 1, - _source: field, - }) - .then((resp) => { - if (resp.hits.total !== 0 && resp.hits.hits.length) { - const hit = resp.hits.hits[0]; - if (hit._source && hit._source[field]) { - obj.time = hit._source[field]; + // console.log('fields: ', fields); + const fieldsList = Object.keys(fields); + if (fieldsList.length) { + body._source = fieldsList; } } - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); - }); - } - searchPreview(job) { - return $q((resolve, reject) => { + const data = { + index: job.datafeed_config.indices, + body + }; - if (job.datafeed_config) { - - // if query is set, add it to the search, otherwise use match_all - let query = { 'match_all': {} }; - if (job.datafeed_config.query) { - query = job.datafeed_config.query; - } + ml.esSearch(data) + .then((resp) => { + resolve(resp); + }) + .catch((resp) => { + reject(resp); + }); - // Get bucket span - // Get first doc time for datafeed - // Create a new query - must user query and must range query. - // Time range 'to' first doc time plus < 10 buckets - - // Do a preliminary search to get the date of the earliest doc matching the - // query in the datafeed. This will be used to apply a time range criteria - // on the datafeed search preview. - // This time filter is required for datafeed searches using aggregations to ensure - // the search does not create too many buckets (default 10000 max_bucket limit), - // but apply it to searches without aggregations too for consistency. - ml.getTimeFieldRange({ - index: job.datafeed_config.indices, - timeFieldName: job.data_description.time_field, - query }) - .then((timeRange) => { - const bucketSpan = parseInterval(job.analysis_config.bucket_span); - const earliestMs = timeRange.start.epoch; - const latestMs = +timeRange.start.epoch + (10 * bucketSpan.asMilliseconds()); - - const body = { - query: { - bool: { - must: [ - { - range: { - [job.data_description.time_field]: { - gte: earliestMs, - lt: latestMs, - format: 'epoch_millis' - } - } - }, - query - ] - } - } - }; - - // if aggs or aggregations is set, add it to the search - const aggregations = job.datafeed_config.aggs || job.datafeed_config.aggregations; - if (aggregations && Object.keys(aggregations).length) { - body.size = 0; - body.aggregations = aggregations; - - // add script_fields if present - const scriptFields = job.datafeed_config.script_fields; - if (scriptFields && Object.keys(scriptFields).length) { - body.script_fields = scriptFields; - } - - } else { - // if aggregations is not set and retrieveWholeSource is not set, add all of the fields from the job - body.size = ML_DATA_PREVIEW_COUNT; - - // add script_fields if present - const scriptFields = job.datafeed_config.script_fields; - if (scriptFields && Object.keys(scriptFields).length) { - body.script_fields = scriptFields; - } - - const fields = {}; - - // get fields from detectors - if (job.analysis_config.detectors) { - _.each(job.analysis_config.detectors, (dtr) => { - if (dtr.by_field_name) { - fields[dtr.by_field_name] = {}; - } - if (dtr.field_name) { - fields[dtr.field_name] = {}; - } - if (dtr.over_field_name) { - fields[dtr.over_field_name] = {}; - } - if (dtr.partition_field_name) { - fields[dtr.partition_field_name] = {}; - } - }); - } - - // get fields from influencers - if (job.analysis_config.influencers) { - _.each(job.analysis_config.influencers, (inf) => { - fields[inf] = {}; - }); - } + .catch((resp) => { + reject(resp); + }); - // get fields from categorizationFieldName - if (job.analysis_config.categorization_field_name) { - fields[job.analysis_config.categorization_field_name] = {}; - } - // get fields from summary_count_field_name - if (job.analysis_config.summary_count_field_name) { - fields[job.analysis_config.summary_count_field_name] = {}; - } + } - // get fields from time_field - if (job.data_description.time_field) { - fields[job.data_description.time_field] = {}; - } + }); + } - // console.log('fields: ', fields); - const fieldsList = Object.keys(fields); - if (fieldsList.length) { - body._source = fieldsList; - } - } + openJob(jobId) { + return ml.openJob({ jobId }); + } - const data = { - index: job.datafeed_config.indices, - body - }; - - es.search(data) - .then((resp) => { - resolve(resp); - }) - .catch((resp) => { - reject(resp); - }); + closeJob(jobId) { + return ml.closeJob({ jobId }); + } + forceCloseJob(jobId) { + return ml.forceCloseJob({ jobId }); + } - }) - .catch((resp) => { - reject(resp); - }); + saveNewDatafeed(datafeedConfig, jobId) { + const datafeedId = `datafeed-${jobId}`; + datafeedConfig.job_id = jobId; - } + return ml.addDatafeed({ + datafeedId, + datafeedConfig + }); + } + updateDatafeed(datafeedId, datafeedConfig) { + return ml.updateDatafeed({ datafeedId, datafeedConfig }) + .then((resp) => { + console.log('update datafeed', resp); + return { success: true }; + }) + .catch((err) => { + msgs.error('Could not update datafeed: ' + datafeedId); + console.log('update datafeed', err); + return { success: false, message: err.message }; }); - } - - openJob(jobId) { - return $q.when(ml.openJob({ jobId })); - } + } - closeJob(jobId) { - return $q.when(ml.closeJob({ jobId })); - } + deleteDatafeed() { - forceCloseJob(jobId) { - return $q.when(ml.forceCloseJob({ jobId })); - } + } + // start the datafeed for a given job + // refresh the job state on start success + startDatafeed(datafeedId, jobId, start, end) { + return new Promise((resolve, reject) => { - saveNewDatafeed(datafeedConfig, jobId) { - const datafeedId = `datafeed-${jobId}`; - datafeedConfig.job_id = jobId; + // if the end timestamp is a number, add one ms to it to make it + // inclusive of the end of the data + if (_.isNumber(end)) { + end++; + } - return $q.when(ml.addDatafeed({ + ml.startDatafeed({ datafeedId, - datafeedConfig - })); - } - - updateDatafeed(datafeedId, datafeedConfig) { - return $q.when(ml.updateDatafeed({ datafeedId, datafeedConfig })) + start, + end + }) .then((resp) => { - console.log('update datafeed', resp); - return { success: true }; + resolve(resp); }) .catch((err) => { - msgs.error('Could not update datafeed: ' + datafeedId); - console.log('update datafeed', err); - return { success: false, message: err.message }; + console.log('jobService error starting datafeed:', err); + msgs.error('Could not start datafeed for ' + jobId, err); + reject(err); }); - } - - deleteDatafeed() { - - } - - // start the datafeed for a given job - // refresh the job state on start success - startDatafeed(datafeedId, jobId, start, end) { - return $q((resolve, reject) => { - - // if the end timestamp is a number, add one ms to it to make it - // inclusive of the end of the data - if (_.isNumber(end)) { - end++; - } + }); + } - ml.startDatafeed({ - datafeedId, - start, - end + // stop the datafeed for a given job + // refresh the job state on stop success + stopDatafeed(datafeedId, jobId) { + return new Promise((resolve, reject) => { + ml.stopDatafeed({ + datafeedId + }) + .then((resp) => { + resolve(resp); }) - .then((resp) => { - resolve(resp); - }) - .catch((err) => { - console.log('jobService error starting datafeed:', err); - msgs.error('Could not start datafeed for ' + jobId, err); - reject(err); - }); - }); - } + .catch((err) => { + console.log('jobService error stopping datafeed:', err); + if (err.statusCode === 500) { + msgs.error('Could not stop datafeed for ' + jobId); + msgs.error('Request may have timed out and may still be running in the background.'); + } else { + msgs.error('Could not stop datafeed for ' + jobId, err); + } + reject(err); + }); + }); + } - // stop the datafeed for a given job - // refresh the job state on stop success - stopDatafeed(datafeedId, jobId) { - return $q((resolve, reject) => { - ml.stopDatafeed({ - datafeedId - }) + validateDetector(detector) { + return new Promise((resolve, reject) => { + if (detector) { + ml.validateDetector({ detector }) .then((resp) => { resolve(resp); }) - .catch((err) => { - console.log('jobService error stopping datafeed:', err); - if (err.statusCode === 500) { - msgs.error('Could not stop datafeed for ' + jobId); - msgs.error('Request may have timed out and may still be running in the background.'); - } else { - msgs.error('Could not stop datafeed for ' + jobId, err); - } - reject(err); + .catch((resp) => { + reject(resp); }); - }); - } - - validateDetector(detector) { - return $q((resolve, reject) => { - if (detector) { - ml.validateDetector({ detector }) - .then((resp) => { - resolve(resp); - }) - .catch((resp) => { - reject(resp); - }); - } else { - reject({}); - } - }); - } - - getDatafeedId(jobId) { - let datafeedId = datafeedIds[jobId]; - if (datafeedId === undefined) { - datafeedId = `datafeed-${jobId}`; + } else { + reject({}); } - return datafeedId; - } - - getDatafeedPreview(jobId) { - const datafeedId = this.getDatafeedId(jobId); - return $q.when(ml.datafeedPreview({ datafeedId })); - } - - // get the list of job group ids as well as how many jobs are in each group - getJobGroups() { - const groups = []; - const tempGroups = {}; - this.jobs.forEach(job => { - if (Array.isArray(job.groups)) { - job.groups.forEach(group => { - if (tempGroups[group] === undefined) { - tempGroups[group] = [job]; - } else { - tempGroups[group].push(job); - } - }); - } - }); - _.each(tempGroups, (js, id) => { - groups.push({ id, jobs: js }); - }); - return groups; - } + }); } - // private function used to check the job saving response - function checkSaveResponse(resp, origJob) { - if (resp) { - if (resp.job_id) { - if (resp.job_id === origJob.job_id) { - console.log('checkSaveResponse(): save successful'); - return true; - } - } else { - if (resp.errorCode) { - console.log('checkSaveResponse(): save failed', resp); - return false; - } - } - } else { - console.log('checkSaveResponse(): response is empty'); - return false; + getDatafeedId(jobId) { + let datafeedId = datafeedIds[jobId]; + if (datafeedId === undefined) { + datafeedId = `datafeed-${jobId}`; } + return datafeedId; } - function processBasicJobInfo(localJobService, jobsList) { - // Process the list of job data obtained from the jobs endpoint to return - // an array of objects containing the basic information (id, description, bucketSpan, detectors - // and detectorDescriptions properties, plus a customUrls key if custom URLs - // have been configured for the job) used by various result dashboards in the ml plugin. - // The key information is stored in the jobService object for quick access. - const processedJobsList = []; - let detectorDescriptionsByJob = {}; - const detectorsByJob = {}; - const customUrlsByJob = {}; - - // use cloned copy of jobs list so not to alter the original - const jobsListCopy = _.cloneDeep(jobsList); - - _.each(jobsListCopy, (jobObj) => { - const analysisConfig = jobObj.analysis_config; - const bucketSpan = parseInterval(analysisConfig.bucket_span); - - const job = { - id: jobObj.job_id, - bucketSpanSeconds: bucketSpan.asSeconds() - }; - - if (_.has(jobObj, 'description') && /^\s*$/.test(jobObj.description) === false) { - job.description = jobObj.description; - } else { - // Just use the id as the description. - job.description = jobObj.job_id; - } - - job.detectorDescriptions = []; - job.detectors = []; - const detectors = _.get(analysisConfig, 'detectors', []); - _.each(detectors, (detector)=> { - if (_.has(detector, 'detector_description')) { - job.detectorDescriptions.push(detector.detector_description); - job.detectors.push(detector); - } - }); - + getDatafeedPreview(jobId) { + const datafeedId = this.getDatafeedId(jobId); + return ml.datafeedPreview({ datafeedId }); + } - if (_.has(jobObj, 'custom_settings.custom_urls')) { - job.customUrls = []; - _.each(jobObj.custom_settings.custom_urls, (url) => { - if (_.has(url, 'url_name') && _.has(url, 'url_value') && isWebUrl(url.url_value)) { - // Only make web URLs (i.e. http or https) available in dashboard drilldowns. - job.customUrls.push(url); + // get the list of job group ids as well as how many jobs are in each group + getJobGroups() { + const groups = []; + const tempGroups = {}; + this.jobs.forEach(job => { + if (Array.isArray(job.groups)) { + job.groups.forEach(group => { + if (tempGroups[group] === undefined) { + tempGroups[group] = [job]; + } else { + tempGroups[group].push(job); } }); - // Only add an entry for a job if customUrls have been defined. - if (job.customUrls.length > 0) { - customUrlsByJob[job.id] = job.customUrls; - } } - - localJobService.jobDescriptions[job.id] = job.description; - detectorDescriptionsByJob[job.id] = job.detectorDescriptions; - detectorsByJob[job.id] = job.detectors; - localJobService.basicJobs[job.id] = job; - processedJobsList.push(job); }); - - detectorDescriptionsByJob = labelDuplicateDetectorDescriptions(detectorDescriptionsByJob); - _.each(detectorsByJob, (dtrs, jobId) => { - _.each(dtrs, (dtr, i) => { - dtr.detector_description = detectorDescriptionsByJob[jobId][i]; - }); + _.each(tempGroups, (js, id) => { + groups.push({ id, jobs: js }); }); - localJobService.detectorsByJob = detectorsByJob; - localJobService.customUrlsByJob = customUrlsByJob; - - return processedJobsList; + return groups; } +} - // Loop through the jobs list and create basic stats - // stats are displayed along the top of the Jobs Management page - function createJobStats(jobsList, jobStats) { - - jobStats.activeNodes.value = 0; - jobStats.total.value = 0; - jobStats.open.value = 0; - jobStats.closed.value = 0; - jobStats.failed.value = 0; - jobStats.activeDatafeeds.value = 0; - - // object to keep track of nodes being used by jobs - const mlNodes = {}; - let failedJobs = 0; - - _.each(jobsList, (job) => { - if (job.state === 'opened') { - jobStats.open.value++; - } else if (job.state === 'closed') { - jobStats.closed.value++; - } else if (job.state === 'failed') { - failedJobs++; +// private function used to check the job saving response +function checkSaveResponse(resp, origJob) { + if (resp) { + if (resp.job_id) { + if (resp.job_id === origJob.job_id) { + console.log('checkSaveResponse(): save successful'); + return true; } + } else { + if (resp.errorCode) { + console.log('checkSaveResponse(): save failed', resp); + return false; + } + } + } else { + console.log('checkSaveResponse(): response is empty'); + return false; + } +} - if (job.datafeed_config && job.datafeed_config.state === 'started') { - jobStats.activeDatafeeds.value++; +function processBasicJobInfo(localJobService, jobsList) { + // Process the list of job data obtained from the jobs endpoint to return + // an array of objects containing the basic information (id, description, bucketSpan, detectors + // and detectorDescriptions properties, plus a customUrls key if custom URLs + // have been configured for the job) used by various result dashboards in the ml plugin. + // The key information is stored in the jobService object for quick access. + const processedJobsList = []; + let detectorDescriptionsByJob = {}; + const detectorsByJob = {}; + const customUrlsByJob = {}; + + // use cloned copy of jobs list so not to alter the original + const jobsListCopy = _.cloneDeep(jobsList); + + _.each(jobsListCopy, (jobObj) => { + const analysisConfig = jobObj.analysis_config; + const bucketSpan = parseInterval(analysisConfig.bucket_span); + + const job = { + id: jobObj.job_id, + bucketSpanSeconds: bucketSpan.asSeconds() + }; + + if (_.has(jobObj, 'description') && /^\s*$/.test(jobObj.description) === false) { + job.description = jobObj.description; + } else { + // Just use the id as the description. + job.description = jobObj.job_id; + } + + job.detectorDescriptions = []; + job.detectors = []; + const detectors = _.get(analysisConfig, 'detectors', []); + _.each(detectors, (detector)=> { + if (_.has(detector, 'detector_description')) { + job.detectorDescriptions.push(detector.detector_description); + job.detectors.push(detector); } + }); + - if (job.node && job.node.name) { - mlNodes[job.node.name] = {}; + if (_.has(jobObj, 'custom_settings.custom_urls')) { + job.customUrls = []; + _.each(jobObj.custom_settings.custom_urls, (url) => { + if (_.has(url, 'url_name') && _.has(url, 'url_value') && isWebUrl(url.url_value)) { + // Only make web URLs (i.e. http or https) available in dashboard drilldowns. + job.customUrls.push(url); + } + }); + // Only add an entry for a job if customUrls have been defined. + if (job.customUrls.length > 0) { + customUrlsByJob[job.id] = job.customUrls; } + } + + localJobService.jobDescriptions[job.id] = job.description; + detectorDescriptionsByJob[job.id] = job.detectorDescriptions; + detectorsByJob[job.id] = job.detectors; + localJobService.basicJobs[job.id] = job; + processedJobsList.push(job); + }); + + detectorDescriptionsByJob = labelDuplicateDetectorDescriptions(detectorDescriptionsByJob); + _.each(detectorsByJob, (dtrs, jobId) => { + _.each(dtrs, (dtr, i) => { + dtr.detector_description = detectorDescriptionsByJob[jobId][i]; }); + }); + localJobService.detectorsByJob = detectorsByJob; + localJobService.customUrlsByJob = customUrlsByJob; - jobStats.total.value = jobsList.length; + return processedJobsList; +} - // // Only show failed jobs if it is non-zero - if (failedJobs) { - jobStats.failed.value = failedJobs; - jobStats.failed.show = true; - } else { - jobStats.failed.show = false; +// Loop through the jobs list and create basic stats +// stats are displayed along the top of the Jobs Management page +function createJobStats(jobsList, jobStats) { + + jobStats.activeNodes.value = 0; + jobStats.total.value = 0; + jobStats.open.value = 0; + jobStats.closed.value = 0; + jobStats.failed.value = 0; + jobStats.activeDatafeeds.value = 0; + + // object to keep track of nodes being used by jobs + const mlNodes = {}; + let failedJobs = 0; + + _.each(jobsList, (job) => { + if (job.state === 'opened') { + jobStats.open.value++; + } else if (job.state === 'closed') { + jobStats.closed.value++; + } else if (job.state === 'failed') { + failedJobs++; } - jobStats.activeNodes.value = Object.keys(mlNodes).length; - } + if (job.datafeed_config && job.datafeed_config.state === 'started') { + jobStats.activeDatafeeds.value++; + } - function createJobUrls(jobsList, jobUrls) { - _.each(jobsList, (job) => { - if (job.data_counts) { - const from = moment(job.data_counts.earliest_record_timestamp).toISOString(); - const to = moment(job.data_counts.latest_record_timestamp).toISOString(); - let path = `?_g=(ml:(jobIds:!('${job.job_id}'))`; - path += `,refreshInterval:(display:Off,pause:!f,value:0),time:(from:'${from}'`; - path += `,mode:absolute,to:'${to}'`; - path += '))&_a=(filters:!(),query:(query_string:(analyze_wildcard:!t,query:\'*\')))'; - - if (jobUrls[job.job_id]) { - jobUrls[job.job_id].url = path; - } else { - jobUrls[job.job_id] = { url: path }; - } - } - }); - } + if (job.node && job.node.name) { + mlNodes[job.node.name] = {}; + } + }); + + jobStats.total.value = jobsList.length; - if (jobService === undefined) { - jobService = new JobService(); + // // Only show failed jobs if it is non-zero + if (failedJobs) { + jobStats.failed.value = failedJobs; + jobStats.failed.show = true; + } else { + jobStats.failed.show = false; } - return jobService; + + jobStats.activeNodes.value = Object.keys(mlNodes).length; } + +function createJobUrls(jobsList, jobUrls) { + _.each(jobsList, (job) => { + if (job.data_counts) { + const from = moment(job.data_counts.earliest_record_timestamp).toISOString(); + const to = moment(job.data_counts.latest_record_timestamp).toISOString(); + let path = `?_g=(ml:(jobIds:!('${job.job_id}'))`; + path += `,refreshInterval:(display:Off,pause:!f,value:0),time:(from:'${from}'`; + path += `,mode:absolute,to:'${to}'`; + path += '))&_a=(filters:!(),query:(query_string:(analyze_wildcard:!t,query:\'*\')))'; + + if (jobUrls[job.job_id]) { + jobUrls[job.job_id].url = path; + } else { + jobUrls[job.job_id] = { url: path }; + } + } + }); +} + +export const mlJobService = new JobService(); diff --git a/x-pack/plugins/ml/public/services/ml_api_service.js b/x-pack/plugins/ml/public/services/ml_api_service/index.js similarity index 97% rename from x-pack/plugins/ml/public/services/ml_api_service.js rename to x-pack/plugins/ml/public/services/ml_api_service/index.js index 6eb3e357883255..a91cdf258d2d53 100644 --- a/x-pack/plugins/ml/public/services/ml_api_service.js +++ b/x-pack/plugins/ml/public/services/ml_api_service/index.js @@ -9,7 +9,9 @@ import { pick } from 'lodash'; import chrome from 'ui/chrome'; -import { http } from './http_service'; +import { http } from 'plugins/ml/services/http_service'; + +import { results } from './results'; const basePath = chrome.addBasePath('/api/ml'); @@ -394,5 +396,15 @@ export const ml = { method: 'POST', data }); - } + }, + + esSearch(obj) { + return http({ + url: `${basePath}/es_search`, + method: 'POST', + data: obj + }); + }, + + results }; diff --git a/x-pack/plugins/ml/public/services/ml_api_service/results.js b/x-pack/plugins/ml/public/services/ml_api_service/results.js new file mode 100644 index 00000000000000..5f7b76ce268655 --- /dev/null +++ b/x-pack/plugins/ml/public/services/ml_api_service/results.js @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// Service for obtaining data for the ML Results dashboards. + +import chrome from 'ui/chrome'; + +import { http } from 'plugins/ml/services/http_service'; + +const basePath = chrome.addBasePath('/api/ml'); + +export const results = { + getAnomaliesTableData( + jobIds, + criteriaFields, + influencers, + aggregationInterval, + threshold, + earliestMs, + latestMs, + maxRecords, + maxExamples) { + + return http({ + url: `${basePath}/results/anomalies_table_data`, + method: 'POST', + data: { + jobIds, + criteriaFields, + influencers, + aggregationInterval, + threshold, + earliestMs, + latestMs, + maxRecords, + maxExamples + } + }); + }, + + getCategoryDefinition(jobId, categoryId) { + return http({ + url: `${basePath}/results/category_definition`, + method: 'POST', + data: { jobId, categoryId } + }); + }, + + getCategoryExamples( + jobId, + categoryIds, + maxExamples + ) { + + return http({ + url: `${basePath}/results/category_examples`, + method: 'POST', + data: { + jobId, + categoryIds, + maxExamples + } + }); + } +}; diff --git a/x-pack/plugins/ml/public/services/results_service.js b/x-pack/plugins/ml/public/services/results_service.js index 0d64220bfbbaa5..fb13ed381ab301 100644 --- a/x-pack/plugins/ml/public/services/results_service.js +++ b/x-pack/plugins/ml/public/services/results_service.js @@ -12,101 +12,376 @@ import _ from 'lodash'; import { ML_MEDIAN_PERCENTS } from 'plugins/ml/../common/util/job_utils'; import { escapeForElasticsearchQuery } from 'plugins/ml/util/string_utils'; -import { ML_RESULTS_INDEX_PATTERN } from 'plugins/ml/constants/index_patterns'; +import { ML_RESULTS_INDEX_PATTERN } from 'plugins/ml/../common/constants/index_patterns'; import { ml } from 'plugins/ml/services/ml_api_service'; -export function ResultsServiceProvider($q, es) { + // Obtains the maximum bucket anomaly scores by job ID and time. // Pass an empty array or ['*'] to search over all job IDs. // Returned response contains a results property, with a key for job // which has results for the specified time range. - function getScoresByBucket(jobIds, earliestMs, latestMs, interval, maxResults) { - return $q((resolve, reject) => { - const obj = { - success: true, - results: {} - }; +function getScoresByBucket(jobIds, earliestMs, latestMs, interval, maxResults) { + return new Promise((resolve, reject) => { + const obj = { + success: true, + results: {} + }; + + // Build the criteria to use in the bool filter part of the request. + // Adds criteria for the time range plus any specified job IDs. + const boolCriteria = [ + { + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' + } + } + } + ]; + + if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { + let jobIdFilterStr = ''; + _.each(jobIds, (jobId, i) => { + if (i > 0) { + jobIdFilterStr += ' OR '; + } + jobIdFilterStr += 'job_id:'; + jobIdFilterStr += jobId; + }); + boolCriteria.push({ + query_string: { + analyze_wildcard: false, + query: jobIdFilterStr + } + }); + } - // Build the criteria to use in the bool filter part of the request. - // Adds criteria for the time range plus any specified job IDs. - const boolCriteria = [ - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: [{ + query_string: { + query: 'result_type:bucket', + analyze_wildcard: false + } + }, { + bool: { + must: boolCriteria + } + }] + } + }, + aggs: { + jobId: { + terms: { + field: 'job_id', + size: maxResults !== undefined ? maxResults : 5, + order: { + anomalyScore: 'desc' + } + }, + aggs: { + anomalyScore: { + max: { + field: 'anomaly_score' + } + }, + byTime: { + date_histogram: { + field: 'timestamp', + interval: interval, + min_doc_count: 1, + extended_bounds: { + min: earliestMs, + max: latestMs + } + }, + aggs: { + anomalyScore: { + max: { + field: 'anomaly_score' + } + } + } + } } } } - ]; + } + }) + .then((resp) => { + const dataByJobId = _.get(resp, ['aggregations', 'jobId', 'buckets'], []); + _.each(dataByJobId, (dataForJob) => { + const jobId = dataForJob.key; - if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { - let jobIdFilterStr = ''; - _.each(jobIds, (jobId, i) => { - if (i > 0) { - jobIdFilterStr += ' OR '; - } - jobIdFilterStr += 'job_id:'; - jobIdFilterStr += jobId; + const resultsForTime = {}; + + const dataByTime = _.get(dataForJob, ['byTime', 'buckets'], []); + _.each(dataByTime, (dataForTime) => { + const value = _.get(dataForTime, ['anomalyScore', 'value']); + if (value !== undefined) { + const time = dataForTime.key; + resultsForTime[time] = _.get(dataForTime, ['anomalyScore', 'value']); + } + }); + obj.results[jobId] = resultsForTime; }); - boolCriteria.push({ - query_string: { - analyze_wildcard: false, - query: jobIdFilterStr + + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); +} + +// Obtains a list of scheduled events by job ID and time. +// Pass an empty array or ['*'] to search over all job IDs. +// Returned response contains a events property, which will only +// contains keys for jobs which have scheduled events for the specified time range. +function getScheduledEventsByBucket( + jobIds, + earliestMs, + latestMs, + interval, + maxJobs, + maxEvents) { + return new Promise((resolve, reject) => { + const obj = { + success: true, + events: {} + }; + + // Build the criteria to use in the bool filter part of the request. + // Adds criteria for the time range plus any specified job IDs. + const boolCriteria = [ + { + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' + } + } + }, + { + exists: { field: 'scheduled_events' } + } + ]; + + if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { + let jobIdFilterStr = ''; + _.each(jobIds, (jobId, i) => { + jobIdFilterStr += `${i > 0 ? ' OR ' : ''}job_id:${jobId}`; + }); + boolCriteria.push({ + query_string: { + analyze_wildcard: false, + query: jobIdFilterStr + } + }); + } + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: [{ + query_string: { + query: 'result_type:bucket', + analyze_wildcard: false + } + }, { + bool: { + must: boolCriteria + } + }] + } + }, + aggs: { + jobs: { + terms: { + field: 'job_id', + min_doc_count: 1, + size: maxJobs + }, + aggs: { + times: { + date_histogram: { + field: 'timestamp', + interval: interval, + min_doc_count: 1 + }, + aggs: { + events: { + terms: { + field: 'scheduled_events', + size: maxEvents + } + } + } + } + } } + } + } + }) + .then((resp) => { + const dataByJobId = _.get(resp, ['aggregations', 'jobs', 'buckets'], []); + _.each(dataByJobId, (dataForJob) => { + const jobId = dataForJob.key; + const resultsForTime = {}; + const dataByTime = _.get(dataForJob, ['times', 'buckets'], []); + _.each(dataByTime, (dataForTime) => { + const time = dataForTime.key; + const events = _.get(dataForTime, ['events', 'buckets']); + resultsForTime[time] = _.map(events, 'key'); + }); + obj.events[jobId] = resultsForTime; }); + + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); +} + + +// Obtains the top influencers, by maximum influencer score, for the specified index, time range and job ID(s). +// Pass an empty array or ['*'] to search over all job IDs. +// An optional array of influencers may be supplied, with each object in the array having 'fieldName' +// and 'fieldValue' properties, to limit data to the supplied list of influencers. +// Returned response contains an influencers property, with a key for each of the influencer field names, +// whose value is an array of objects containing influencerFieldValue, maxAnomalyScore and sumAnomalyScore keys. +function getTopInfluencers( + jobIds, + earliestMs, + latestMs, + maxFieldValues = 10, + influencers = []) { + return new Promise((resolve, reject) => { + const obj = { success: true, influencers: {} }; + + // Build the criteria to use in the bool filter part of the request. + // Adds criteria for the time range plus any specified job IDs. + const boolCriteria = [ + { + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' + } + } + }, + { + range: { + influencer_score: { + gt: 0 + } + } } + ]; - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: [{ + if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { + let jobIdFilterStr = ''; + _.each(jobIds, (jobId, i) => { + if (i > 0) { + jobIdFilterStr += ' OR '; + } + jobIdFilterStr += 'job_id:'; + jobIdFilterStr += jobId; + }); + boolCriteria.push({ + query_string: { + analyze_wildcard: false, + query: jobIdFilterStr + } + }); + } + + // Add a should query to filter for each of the specified influencers. + if (influencers.length > 0) { + boolCriteria.push({ + bool: { + should: influencers.map((influencer) => { + return { + bool: { + must: [ + { term: { influencer_field_name: influencer.fieldName } }, + { term: { influencer_field_value: influencer.fieldValue } } + ] + } + }; + }), + minimum_should_match: 1, + } + }); + } + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: [ + { query_string: { - query: 'result_type:bucket', + query: 'result_type:influencer', analyze_wildcard: false } - }, { + }, + { bool: { must: boolCriteria } - }] - } - }, - aggs: { - jobId: { - terms: { - field: 'job_id', - size: maxResults !== undefined ? maxResults : 5, - order: { - anomalyScore: 'desc' + } + ] + } + }, + aggs: { + influencerFieldNames: { + terms: { + field: 'influencer_field_name', + size: 5, + order: { + maxAnomalyScore: 'desc' + } + }, + aggs: { + maxAnomalyScore: { + max: { + field: 'influencer_score' } }, - aggs: { - anomalyScore: { - max: { - field: 'anomaly_score' + influencerFieldValues: { + terms: { + field: 'influencer_field_value', + size: maxFieldValues, + order: { + maxAnomalyScore: 'desc' } }, - byTime: { - date_histogram: { - field: 'timestamp', - interval: interval, - min_doc_count: 1, - extended_bounds: { - min: earliestMs, - max: latestMs + aggs: { + maxAnomalyScore: { + max: { + field: 'influencer_score' } }, - aggs: { - anomalyScore: { - max: { - field: 'anomaly_score' - } + sumAnomalyScore: { + sum: { + field: 'influencer_score' } } } @@ -114,242 +389,283 @@ export function ResultsServiceProvider($q, es) { } } } - }) - .then((resp) => { - const dataByJobId = _.get(resp, ['aggregations', 'jobId', 'buckets'], []); - _.each(dataByJobId, (dataForJob) => { - const jobId = dataForJob.key; - - const resultsForTime = {}; - - const dataByTime = _.get(dataForJob, ['byTime', 'buckets'], []); - _.each(dataByTime, (dataForTime) => { - const value = _.get(dataForTime, ['anomalyScore', 'value']); - if (value !== undefined) { - const time = dataForTime.key; - resultsForTime[time] = _.get(dataForTime, ['anomalyScore', 'value']); - } - }); - obj.results[jobId] = resultsForTime; + } + }) + .then((resp) => { + const fieldNameBuckets = _.get(resp, ['aggregations', 'influencerFieldNames', 'buckets'], []); + _.each(fieldNameBuckets, (nameBucket) => { + const fieldName = nameBucket.key; + const fieldValues = []; + + const fieldValueBuckets = _.get(nameBucket, ['influencerFieldValues', 'buckets'], []); + _.each(fieldValueBuckets, (valueBucket) => { + const fieldValueResult = { + influencerFieldValue: valueBucket.key, + maxAnomalyScore: valueBucket.maxAnomalyScore.value, + sumAnomalyScore: valueBucket.sumAnomalyScore.value + }; + fieldValues.push(fieldValueResult); }); - resolve(obj); - }) - .catch((resp) => { - reject(resp); + obj.influencers[fieldName] = fieldValues; }); - }); - } - - // Obtains a list of scheduled events by job ID and time. - // Pass an empty array or ['*'] to search over all job IDs. - // Returned response contains a events property, which will only - // contains keys for jobs which have scheduled events for the specified time range. - function getScheduledEventsByBucket( - jobIds, - earliestMs, - latestMs, - interval, - maxJobs, - maxEvents) { - return $q((resolve, reject) => { - const obj = { - success: true, - events: {} - }; - // Build the criteria to use in the bool filter part of the request. - // Adds criteria for the time range plus any specified job IDs. - const boolCriteria = [ - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } - } - }, - { - exists: { field: 'scheduled_events' } - } - ]; + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); +} - if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { - let jobIdFilterStr = ''; - _.each(jobIds, (jobId, i) => { - jobIdFilterStr += `${i > 0 ? ' OR ' : ''}job_id:${jobId}`; - }); - boolCriteria.push({ - query_string: { - analyze_wildcard: false, - query: jobIdFilterStr - } - }); +// Obtains the top influencer field values, by maximum anomaly score, for a +// particular index, field name and job ID(s). +// Pass an empty array or ['*'] to search over all job IDs. +// Returned response contains a results property, which is an array of objects +// containing influencerFieldValue, maxAnomalyScore and sumAnomalyScore keys. +function getTopInfluencerValues(jobIds, influencerFieldName, earliestMs, latestMs, maxResults) { + return new Promise((resolve, reject) => { + const obj = { success: true, results: [] }; + + // Build the criteria to use in the bool filter part of the request. + // Adds criteria for the time range plus any specified job IDs. + const boolCriteria = [{ + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' + } } + }]; - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: [{ + if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { + let jobIdFilterStr = ''; + _.each(jobIds, (jobId, i) => { + if (i > 0) { + jobIdFilterStr += ' OR '; + } + jobIdFilterStr += 'job_id:'; + jobIdFilterStr += jobId; + }); + boolCriteria.push({ + query_string: { + analyze_wildcard: false, + query: jobIdFilterStr + } + }); + } + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: [ + { query_string: { - query: 'result_type:bucket', + query: `result_type:influencer AND influencer_field_name: ${escapeForElasticsearchQuery(influencerFieldName)}`, analyze_wildcard: false } - }, { + }, + { bool: { must: boolCriteria } - }] - } - }, - aggs: { - jobs: { - terms: { - field: 'job_id', - min_doc_count: 1, - size: maxJobs + } + ] + } + }, + aggs: { + influencerFieldValues: { + terms: { + field: 'influencer_field_value', + size: maxResults !== undefined ? maxResults : 2, + order: { + maxAnomalyScore: 'desc' + } + }, + aggs: { + maxAnomalyScore: { + max: { + field: 'influencer_score' + } }, - aggs: { - times: { - date_histogram: { - field: 'timestamp', - interval: interval, - min_doc_count: 1 - }, - aggs: { - events: { - terms: { - field: 'scheduled_events', - size: maxEvents - } - } - } + sumAnomalyScore: { + sum: { + field: 'influencer_score' } } } } } + } + }) + .then((resp) => { + const buckets = _.get(resp, ['aggregations', 'influencerFieldValues', 'buckets'], []); + _.each(buckets, (bucket) => { + const result = { + influencerFieldValue: bucket.key, + maxAnomalyScore: bucket.maxAnomalyScore.value, + sumAnomalyScore: bucket.sumAnomalyScore.value }; + obj.results.push(result); + }); + + resolve(obj); }) - .then((resp) => { - const dataByJobId = _.get(resp, ['aggregations', 'jobs', 'buckets'], []); - _.each(dataByJobId, (dataForJob) => { - const jobId = dataForJob.key; - const resultsForTime = {}; - const dataByTime = _.get(dataForJob, ['times', 'buckets'], []); - _.each(dataByTime, (dataForTime) => { - const time = dataForTime.key; - const events = _.get(dataForTime, ['events', 'buckets']); - resultsForTime[time] = _.map(events, 'key'); - }); - obj.events[jobId] = resultsForTime; - }); + .catch((resp) => { + reject(resp); + }); + }); +} - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); - }); - } - - - // Obtains the top influencers, by maximum influencer score, for the specified index, time range and job ID(s). - // Pass an empty array or ['*'] to search over all job IDs. - // Returned response contains an influencers property, with a key for each of the influencer field names, - // whose value is an array of objects containing influencerFieldValue, maxAnomalyScore and sumAnomalyScore keys. - function getTopInfluencers(jobIds, earliestMs, latestMs, maxFieldNames, maxFieldValues) { - return $q((resolve, reject) => { - const obj = { success: true, influencers: {} }; - - // Build the criteria to use in the bool filter part of the request. - // Adds criteria for the time range plus any specified job IDs. - const boolCriteria = [ - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } +// Obtains the overall bucket scores for the specified job ID(s). +// Pass ['*'] to search over all job IDs. +// Returned response contains a results property as an object of max score by time. +function getOverallBucketScores(jobIds, topN, earliestMs, latestMs, interval) { + return new Promise((resolve, reject) => { + const obj = { success: true, results: {} }; + + ml.overallBuckets({ + jobId: jobIds, + topN: topN, + bucketSpan: interval, + start: earliestMs, + end: latestMs + }) + .then(resp => { + const dataByTime = _.get(resp, ['overall_buckets'], []); + _.each(dataByTime, (dataForTime) => { + const value = _.get(dataForTime, ['overall_score']); + if (value !== undefined) { + obj.results[dataForTime.timestamp] = value; } - } - ]; + }); + + resolve(obj); + }) + .catch(resp => { + reject(resp); + }); + }); +} - if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { - let jobIdFilterStr = ''; - _.each(jobIds, (jobId, i) => { - if (i > 0) { - jobIdFilterStr += ' OR '; +// Obtains the maximum score by influencer_field_value and by time for the specified job ID(s) +// (pass an empty array or ['*'] to search over all job IDs), and specified influencer field +// values (pass an empty array to search over all field values). +// Returned response contains a results property with influencer field values keyed +// against max score by time. +function getInfluencerValueMaxScoreByTime( + jobIds, + influencerFieldName, + influencerFieldValues, + earliestMs, + latestMs, + interval, + maxResults) { + return new Promise((resolve, reject) => { + const obj = { success: true, results: {} }; + + // Build the criteria to use in the bool filter part of the request. + // Adds criteria for the time range plus any specified job IDs. + const boolCriteria = [ + { + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' } - jobIdFilterStr += 'job_id:'; - jobIdFilterStr += jobId; - }); - boolCriteria.push({ - query_string: { - analyze_wildcard: false, - query: jobIdFilterStr + } + }, + { + range: { + influencer_score: { + gt: 0 } - }); + } } + ]; - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: [ - { - query_string: { - query: 'result_type:influencer', - analyze_wildcard: false - } - }, - { - bool: { - must: boolCriteria - } + if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { + let jobIdFilterStr = ''; + _.each(jobIds, (jobId, i) => { + if (i > 0) { + jobIdFilterStr += ' OR '; + } + jobIdFilterStr += `job_id:${jobId}`; + }); + boolCriteria.push({ + query_string: { + analyze_wildcard: false, + query: jobIdFilterStr + } + }); + } + + if (influencerFieldValues && influencerFieldValues.length > 0) { + let influencerFilterStr = ''; + _.each(influencerFieldValues, (value, i) => { + if (i > 0) { + influencerFilterStr += ' OR '; + } + influencerFilterStr += `influencer_field_value:${escapeForElasticsearchQuery(value)}`; + }); + boolCriteria.push({ + query_string: { + analyze_wildcard: false, + query: influencerFilterStr + } + }); + } + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: [ + { + query_string: { + query: `result_type:influencer AND influencer_field_name: ${escapeForElasticsearchQuery(influencerFieldName)}`, + analyze_wildcard: false } - ] - } - }, - aggs: { - influencerFieldNames: { - terms: { - field: 'influencer_field_name', - size: 5, - order: { - maxAnomalyScore: 'desc' + }, + { + bool: { + must: boolCriteria + } + } + ] + } + }, + aggs: { + influencerFieldValues: { + terms: { + field: 'influencer_field_value', + size: maxResults !== undefined ? maxResults : 10, + order: { + maxAnomalyScore: 'desc' + } + }, + aggs: { + maxAnomalyScore: { + max: { + field: 'influencer_score' } }, - aggs: { - maxAnomalyScore: { - max: { - field: 'influencer_score' - } + byTime: { + date_histogram: { + field: 'timestamp', + interval, + min_doc_count: 1 }, - influencerFieldValues: { - terms: { - field: 'influencer_field_value', - size: maxFieldValues !== undefined ? maxFieldValues : 10, - order: { - maxAnomalyScore: 'desc' - } - }, - aggs: { - maxAnomalyScore: { - max: { - field: 'influencer_score' - } - }, - sumAnomalyScore: { - sum: { - field: 'influencer_score' - } + aggs: { + maxAnomalyScore: { + max: { + field: 'influencer_score' } } } @@ -357,46 +673,60 @@ export function ResultsServiceProvider($q, es) { } } } - }) - .then((resp) => { - const fieldNameBuckets = _.get(resp, ['aggregations', 'influencerFieldNames', 'buckets'], []); - _.each(fieldNameBuckets, (nameBucket) => { - const fieldName = nameBucket.key; - const fieldValues = []; - - const fieldValueBuckets = _.get(nameBucket, ['influencerFieldValues', 'buckets'], []); - _.each(fieldValueBuckets, (valueBucket) => { - const fieldValueResult = { - influencerFieldValue: valueBucket.key, - maxAnomalyScore: valueBucket.maxAnomalyScore.value, - sumAnomalyScore: valueBucket.sumAnomalyScore.value - }; - fieldValues.push(fieldValueResult); - }); - - obj.influencers[fieldName] = fieldValues; + } + }) + .then((resp) => { + const fieldValueBuckets = _.get(resp, ['aggregations', 'influencerFieldValues', 'buckets'], []); + _.each(fieldValueBuckets, (valueBucket) => { + const fieldValue = valueBucket.key; + const fieldValues = {}; + + const timeBuckets = _.get(valueBucket, ['byTime', 'buckets'], []); + _.each(timeBuckets, (timeBucket) => { + const time = timeBucket.key; + const score = timeBucket.maxAnomalyScore.value; + fieldValues[time] = score; }); - resolve(obj); - }) - .catch((resp) => { - reject(resp); + obj.results[fieldValue] = fieldValues; }); - }); - } - - // Obtains the top influencer field values, by maximum anomaly score, for a - // particular index, field name and job ID(s). - // Pass an empty array or ['*'] to search over all job IDs. - // Returned response contains a results property, which is an array of objects - // containing influencerFieldValue, maxAnomalyScore and sumAnomalyScore keys. - function getTopInfluencerValues(jobIds, influencerFieldName, earliestMs, latestMs, maxResults) { - return $q((resolve, reject) => { - const obj = { success: true, results: [] }; - - // Build the criteria to use in the bool filter part of the request. - // Adds criteria for the time range plus any specified job IDs. - const boolCriteria = [{ + + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); +} + +// Queries Elasticsearch to obtain record level results containing the influencers +// for the specified job(s), record score threshold, and time range. +// Pass an empty array or ['*'] to search over all job IDs. +// Returned response contains a records property, with each record containing +// only the fields job_id, detector_index, record_score and influencers. +function getRecordInfluencers(jobIds, threshold, earliestMs, latestMs, maxResults) { + return new Promise((resolve, reject) => { + const obj = { success: true, records: [] }; + + // Build the criteria to use in the bool filter part of the request. + // Adds criteria for the existence of the nested influencers field, time range, + // record score, plus any specified job IDs. + const boolCriteria = [ + { + nested: { + path: 'influencers', + query: { + bool: { + must: [ + { + exists: { field: 'influencers' } + } + ] + } + } + } + }, + { range: { timestamp: { gte: earliestMs, @@ -404,620 +734,264 @@ export function ResultsServiceProvider($q, es) { format: 'epoch_millis' } } - }]; - - if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { - let jobIdFilterStr = ''; - _.each(jobIds, (jobId, i) => { - if (i > 0) { - jobIdFilterStr += ' OR '; + }, + { + range: { + record_score: { + gte: threshold, } - jobIdFilterStr += 'job_id:'; - jobIdFilterStr += jobId; - }); - boolCriteria.push({ - query_string: { - analyze_wildcard: false, - query: jobIdFilterStr - } - }); + } } + ]; - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: [ - { - query_string: { - query: `result_type:influencer AND influencer_field_name: ${escapeForElasticsearchQuery(influencerFieldName)}`, - analyze_wildcard: false - } - }, - { - bool: { - must: boolCriteria - } - } - ] - } - }, - aggs: { - influencerFieldValues: { - terms: { - field: 'influencer_field_value', - size: maxResults !== undefined ? maxResults : 2, - order: { - maxAnomalyScore: 'desc' + if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { + let jobIdFilterStr = ''; + _.each(jobIds, (jobId, i) => { + if (i > 0) { + jobIdFilterStr += ' OR '; + } + jobIdFilterStr += 'job_id:'; + jobIdFilterStr += jobId; + }); + boolCriteria.push({ + query_string: { + analyze_wildcard: false, + query: jobIdFilterStr + } + }); + } + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: maxResults !== undefined ? maxResults : 100, + body: { + _source: ['job_id', 'detector_index', 'influencers', 'record_score'], + query: { + bool: { + filter: [ + { + query_string: { + query: 'result_type:record', + analyze_wildcard: false } }, - aggs: { - maxAnomalyScore: { - max: { - field: 'influencer_score' - } - }, - sumAnomalyScore: { - sum: { - field: 'influencer_score' - } + { + bool: { + must: boolCriteria } } - } + ] } + }, + sort: [ + { record_score: { order: 'desc' } } + ], + } + }) + .then((resp) => { + if (resp.hits.total !== 0) { + _.each(resp.hits.hits, (hit) => { + obj.records.push(hit._source); + }); } + resolve(obj); }) - .then((resp) => { - const buckets = _.get(resp, ['aggregations', 'influencerFieldValues', 'buckets'], []); - _.each(buckets, (bucket) => { - const result = { - influencerFieldValue: bucket.key, - maxAnomalyScore: bucket.maxAnomalyScore.value, - sumAnomalyScore: bucket.sumAnomalyScore.value }; - obj.results.push(result); - }); + .catch((resp) => { + reject(resp); + }); + }); +} - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); - }); - } - - // Obtains the overall bucket scores for the specified job ID(s). - // Pass ['*'] to search over all job IDs. - // Returned response contains a results property as an object of max score by time. - function getOverallBucketScores(jobIds, topN, earliestMs, latestMs, interval) { - return $q((resolve, reject) => { - const obj = { success: true, results: {} }; - - ml.overallBuckets({ - jobId: jobIds, - topN: topN, - bucketSpan: interval, - start: earliestMs, - end: latestMs - }) - .then(resp => { - const dataByTime = _.get(resp, ['overall_buckets'], []); - _.each(dataByTime, (dataForTime) => { - const value = _.get(dataForTime, ['overall_score']); - if (value !== undefined) { - obj.results[dataForTime.timestamp] = value; - } - }); - resolve(obj); - }) - .catch(resp => { - reject(resp); - }); - }); - } - - // Obtains the maximum score by influencer_field_value and by time for the specified job ID(s) - // (pass an empty array or ['*'] to search over all job IDs), and specified influencer field - // values (pass an empty array to search over all field values). - // Returned response contains a results property with influencer field values keyed - // against max score by time. - function getInfluencerValueMaxScoreByTime( - jobIds, - influencerFieldName, - influencerFieldValues, - earliestMs, - latestMs, - interval, - maxResults) { - return $q((resolve, reject) => { - const obj = { success: true, results: {} }; - - // Build the criteria to use in the bool filter part of the request. - // Adds criteria for the time range plus any specified job IDs. - const boolCriteria = [ - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } - } - }, - { - range: { - influencer_score: { - gt: 0 - } +// Queries Elasticsearch to obtain the record level results containing the specified influencer(s), +// for the specified job(s), time range, and record score threshold. +// influencers parameter must be an array, with each object in the array having 'fieldName' +// 'fieldValue' properties. The influencer array uses 'should' for the nested bool query, +// so this returns record level results which have at least one of the influencers. +// Pass an empty array or ['*'] to search over all job IDs. +function getRecordsForInfluencer(jobIds, influencers, threshold, earliestMs, latestMs, maxResults) { + return new Promise((resolve, reject) => { + const obj = { success: true, records: [] }; + + // Build the criteria to use in the bool filter part of the request. + // Add criteria for the time range, record score, plus any specified job IDs. + const boolCriteria = [ + { + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' } } - ]; - - if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { - let jobIdFilterStr = ''; - _.each(jobIds, (jobId, i) => { - if (i > 0) { - jobIdFilterStr += ' OR '; - } - jobIdFilterStr += `job_id:${jobId}`; - }); - boolCriteria.push({ - query_string: { - analyze_wildcard: false, - query: jobIdFilterStr - } - }); - } - - if (influencerFieldValues && influencerFieldValues.length > 0) { - let influencerFilterStr = ''; - _.each(influencerFieldValues, (value, i) => { - if (i > 0) { - influencerFilterStr += ' OR '; - } - influencerFilterStr += `influencer_field_value:${escapeForElasticsearchQuery(value)}`; - }); - boolCriteria.push({ - query_string: { - analyze_wildcard: false, - query: influencerFilterStr + }, + { + range: { + record_score: { + gte: threshold, } - }); + } } + ]; - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: [ - { - query_string: { - query: `result_type:influencer AND influencer_field_name: ${escapeForElasticsearchQuery(influencerFieldName)}`, - analyze_wildcard: false - } - }, - { + if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { + let jobIdFilterStr = ''; + _.each(jobIds, (jobId, i) => { + if (i > 0) { + jobIdFilterStr += ' OR '; + } + jobIdFilterStr += 'job_id:'; + jobIdFilterStr += jobId; + }); + boolCriteria.push({ + query_string: { + analyze_wildcard: false, + query: jobIdFilterStr + } + }); + } + + // Add a nested query to filter for each of the specified influencers. + if (influencers.length > 0) { + boolCriteria.push({ + bool: { + should: influencers.map((influencer) => { + return { + nested: { + path: 'influencers', + query: { bool: { - must: boolCriteria + must: [ + { + match: { + 'influencers.influencer_field_name': influencer.fieldName + } + }, + { + match: { + 'influencers.influencer_field_values': influencer.fieldValue + } + } + ] } } - ] - } - }, - aggs: { - influencerFieldValues: { - terms: { - field: 'influencer_field_value', - size: maxResults !== undefined ? maxResults : 10, - order: { - maxAnomalyScore: 'desc' + } + }; + }), + minimum_should_match: 1, + } + }); + } + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: maxResults !== undefined ? maxResults : 100, + body: { + query: { + bool: { + filter: [ + { + query_string: { + query: 'result_type:record', + analyze_wildcard: false } }, - aggs: { - maxAnomalyScore: { - max: { - field: 'influencer_score' - } - }, - byTime: { - date_histogram: { - field: 'timestamp', - interval, - min_doc_count: 1 - }, - aggs: { - maxAnomalyScore: { - max: { - field: 'influencer_score' - } - } - } + { + bool: { + must: boolCriteria } } - } + ] } - } - }) - .then((resp) => { - const fieldValueBuckets = _.get(resp, ['aggregations', 'influencerFieldValues', 'buckets'], []); - _.each(fieldValueBuckets, (valueBucket) => { - const fieldValue = valueBucket.key; - const fieldValues = {}; - - const timeBuckets = _.get(valueBucket, ['byTime', 'buckets'], []); - _.each(timeBuckets, (timeBucket) => { - const time = timeBucket.key; - const score = timeBucket.maxAnomalyScore.value; - fieldValues[time] = score; - }); - - obj.results[fieldValue] = fieldValues; + }, + sort: [ + { record_score: { order: 'desc' } } + ] + } + }) + .then((resp) => { + if (resp.hits.total !== 0) { + _.each(resp.hits.hits, (hit) => { + obj.records.push(hit._source); }); - - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); - }); - } - - - // Obtains the definition of the category with the specified ID and job ID. - // Returned response contains four properties - categoryId, regex, examples - // and terms (space delimited String of the common tokens matched in values of the category). - function getCategoryDefinition(jobId, categoryId) { - return $q((resolve, reject) => { - const obj = { success: true, categoryId: categoryId, terms: null, regex: null, examples: [] }; - - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 1, - body: { - query: { - bool: { - filter: [ - { term: { job_id: jobId } }, - { term: { category_id: categoryId } } - ] - } - } } + resolve(obj); }) - .then((resp) => { - if (resp.hits.total !== 0) { - const source = _.first(resp.hits.hits)._source; - obj.categoryId = source.category_id; - obj.regex = source.regex; - obj.terms = source.terms; - obj.examples = source.examples; - } - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); - }); - } - - - // Obtains the categorization examples for the categories with the specified IDs - // from the given index and job ID. - // Returned response contains two properties - jobId and - // examplesByCategoryId (list of examples against categoryId). - function getCategoryExamples(jobId, categoryIds, maxExamples) { - return $q((resolve, reject) => { - const obj = { success: true, jobId: jobId, examplesByCategoryId: {} }; - - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 500, // Matches size of records in anomaly summary table. - body: { - query: { - bool: { - filter: [ - { term: { job_id: jobId } }, - { terms: { category_id: categoryIds } } - ] - } - } - } - }) - .then((resp) => { - if (resp.hits.total !== 0) { - _.each(resp.hits.hits, (hit) => { - if (maxExamples) { - obj.examplesByCategoryId[hit._source.category_id] = - _.slice(hit._source.examples, 0, Math.min(hit._source.examples.length, maxExamples)); - } else { - obj.examplesByCategoryId[hit._source.category_id] = hit._source.examples; - } + .catch((resp) => { + reject(resp); + }); + }); +} - }); - } - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); - }); - } - - - // Queries Elasticsearch to obtain record level results containing the influencers - // for the specified job(s), record score threshold, and time range. - // Pass an empty array or ['*'] to search over all job IDs. - // Returned response contains a records property, with each record containing - // only the fields job_id, detector_index, record_score and influencers. - function getRecordInfluencers(jobIds, threshold, earliestMs, latestMs, maxResults) { - return $q((resolve, reject) => { - const obj = { success: true, records: [] }; - - // Build the criteria to use in the bool filter part of the request. - // Adds criteria for the existence of the nested influencers field, time range, - // record score, plus any specified job IDs. - const boolCriteria = [ - { - nested: { - path: 'influencers', - query: { - bool: { - must: [ - { - exists: { field: 'influencers' } - } - ] - } - } - } - }, - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } - } - }, - { - range: { - record_score: { - gte: threshold, - } - } - } - ]; - if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { - let jobIdFilterStr = ''; - _.each(jobIds, (jobId, i) => { - if (i > 0) { - jobIdFilterStr += ' OR '; - } - jobIdFilterStr += 'job_id:'; - jobIdFilterStr += jobId; - }); - boolCriteria.push({ - query_string: { - analyze_wildcard: false, - query: jobIdFilterStr +// Queries Elasticsearch to obtain the record level results for the specified job and detector, +// time range, record score threshold, and whether to only return results containing influencers. +// An additional, optional influencer field name and value may also be provided. +function getRecordsForDetector( + jobId, + detectorIndex, + checkForInfluencers, + influencerFieldName, + influencerFieldValue, + threshold, + earliestMs, + latestMs, + maxResults) { + return new Promise((resolve, reject) => { + const obj = { success: true, records: [] }; + + // Build the criteria to use in the bool filter part of the request. + // Add criteria for the time range, record score, plus any specified job IDs. + const boolCriteria = [ + { + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' } - }); - } - - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: maxResults !== undefined ? maxResults : 100, - body: { - _source: ['job_id', 'detector_index', 'influencers', 'record_score'], - query: { - bool: { - filter: [ - { - query_string: { - query: 'result_type:record', - analyze_wildcard: false - } - }, - { - bool: { - must: boolCriteria - } - } - ] - } - }, - sort: [ - { record_score: { order: 'desc' } } - ], } - }) - .then((resp) => { - if (resp.hits.total !== 0) { - _.each(resp.hits.hits, (hit) => { - obj.records.push(hit._source); - }); - } - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); - }); - } - - - // Queries Elasticsearch to obtain the record level results containing the specified influencer(s), - // for the specified job(s), time range, and record score threshold. - // influencers parameter must be an array, with each object in the array having 'fieldName' - // 'fieldValue' properties. The influencer array uses 'should' for the nested bool query, - // so this returns record level results which have at least one of the influencers. - // Pass an empty array or ['*'] to search over all job IDs. - function getRecordsForInfluencer(jobIds, influencers, threshold, earliestMs, latestMs, maxResults) { - return $q((resolve, reject) => { - const obj = { success: true, records: [] }; - - // Build the criteria to use in the bool filter part of the request. - // Add criteria for the time range, record score, plus any specified job IDs. - const boolCriteria = [ - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } - } - }, - { - range: { - record_score: { - gte: threshold, - } + }, + { + term: { job_id: jobId } + }, + { + term: { detector_index: detectorIndex } + }, + { + range: { + record_score: { + gte: threshold, } } - ]; - - if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { - let jobIdFilterStr = ''; - _.each(jobIds, (jobId, i) => { - if (i > 0) { - jobIdFilterStr += ' OR '; - } - jobIdFilterStr += 'job_id:'; - jobIdFilterStr += jobId; - }); - boolCriteria.push({ - query_string: { - analyze_wildcard: false, - query: jobIdFilterStr - } - }); } + ]; - // Add a nested query to filter for each of the specified influencers. - if (influencers.length > 0) { - boolCriteria.push({ - bool: { - should: influencers.map((influencer) => { - return { - nested: { - path: 'influencers', - query: { - bool: { - must: [ - { - match: { - 'influencers.influencer_field_name': influencer.fieldName - } - }, - { - match: { - 'influencers.influencer_field_values': influencer.fieldValue - } - } - ] - } - } - } - }; - }), - minimum_should_match: 1, - } - }); - } - - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: maxResults !== undefined ? maxResults : 100, - body: { + // Add a nested query to filter for the specified influencer field name and value. + if (influencerFieldName && influencerFieldValue) { + boolCriteria.push({ + nested: { + path: 'influencers', query: { bool: { - filter: [ + must: [ { - query_string: { - query: 'result_type:record', - analyze_wildcard: false + match: { + 'influencers.influencer_field_name': influencerFieldName } }, { - bool: { - must: boolCriteria + match: { + 'influencers.influencer_field_values': influencerFieldValue } } ] } - }, - sort: [ - { record_score: { order: 'desc' } } - ] - } - }) - .then((resp) => { - if (resp.hits.total !== 0) { - _.each(resp.hits.hits, (hit) => { - obj.records.push(hit._source); - }); - } - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); - }); - } - - - // Queries Elasticsearch to obtain the record level results for the specified job and detector, - // time range, record score threshold, and whether to only return results containing influencers. - // An additional, optional influencer field name and value may also be provided. - function getRecordsForDetector( - jobId, - detectorIndex, - checkForInfluencers, - influencerFieldName, - influencerFieldValue, - threshold, - earliestMs, - latestMs, - maxResults) { - return $q((resolve, reject) => { - const obj = { success: true, records: [] }; - - // Build the criteria to use in the bool filter part of the request. - // Add criteria for the time range, record score, plus any specified job IDs. - const boolCriteria = [ - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } - } - }, - { - term: { job_id: jobId } - }, - { - term: { detector_index: detectorIndex } - }, - { - range: { - record_score: { - gte: threshold, - } } } - ]; - - // Add a nested query to filter for the specified influencer field name and value. - if (influencerFieldName && influencerFieldValue) { + }); + } else { + if (checkForInfluencers === true) { boolCriteria.push({ nested: { path: 'influencers', @@ -1025,697 +999,670 @@ export function ResultsServiceProvider($q, es) { bool: { must: [ { - match: { - 'influencers.influencer_field_name': influencerFieldName - } - }, - { - match: { - 'influencers.influencer_field_values': influencerFieldValue - } + exists: { field: 'influencers' } } ] } } } }); - } else { - if (checkForInfluencers === true) { - boolCriteria.push({ - nested: { - path: 'influencers', - query: { + } + } + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: maxResults !== undefined ? maxResults : 100, + body: { + query: { + bool: { + filter: [ + { + query_string: { + query: 'result_type:record', + analyze_wildcard: false + } + }, + { bool: { - must: [ - { - exists: { field: 'influencers' } - } - ] + must: boolCriteria } } - } + ] + } + }, + sort: [ + { record_score: { order: 'desc' } } + ], + } + }) + .then((resp) => { + if (resp.hits.total !== 0) { + _.each(resp.hits.hits, (hit) => { + obj.records.push(hit._source); }); } - } + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); +} - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: maxResults !== undefined ? maxResults : 100, - body: { - query: { - bool: { - filter: [ - { - query_string: { - query: 'result_type:record', - analyze_wildcard: false - } - }, - { - bool: { - must: boolCriteria - } - } - ] - } - }, - sort: [ - { record_score: { order: 'desc' } } - ], +// Queries Elasticsearch to obtain all the record level results for the specified job(s), time range, +// and record score threshold. +// Pass an empty array or ['*'] to search over all job IDs. +// Returned response contains a records property, which is an array of the matching results. +function getRecords(jobIds, threshold, earliestMs, latestMs, maxResults) { + return this.getRecordsForInfluencer(jobIds, [], threshold, earliestMs, latestMs, maxResults); +} + +// Queries Elasticsearch to obtain the record level results matching the given criteria, +// for the specified job(s), time range, and record score threshold. +// criteriaFields parameter must be an array, with each object in the array having 'fieldName' +// 'fieldValue' properties. +// Pass an empty array or ['*'] to search over all job IDs. +function getRecordsForCriteria(jobIds, criteriaFields, threshold, earliestMs, latestMs, maxResults) { + return new Promise((resolve, reject) => { + const obj = { success: true, records: [] }; + + // Build the criteria to use in the bool filter part of the request. + // Add criteria for the time range, record score, plus any specified job IDs. + const boolCriteria = [ + { + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' + } } - }) - .then((resp) => { - if (resp.hits.total !== 0) { - _.each(resp.hits.hits, (hit) => { - obj.records.push(hit._source); - }); + }, + { + range: { + record_score: { + gte: threshold, } - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); + } + } + ]; + + if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { + let jobIdFilterStr = ''; + _.each(jobIds, (jobId, i) => { + if (i > 0) { + jobIdFilterStr += ' OR '; + } + jobIdFilterStr += 'job_id:'; + jobIdFilterStr += jobId; + }); + boolCriteria.push({ + query_string: { + analyze_wildcard: false, + query: jobIdFilterStr + } + }); + } + + // Add in term queries for each of the specified criteria. + _.each(criteriaFields, (criteria) => { + boolCriteria.push({ + term: { + [criteria.fieldName]: criteria.fieldValue + } + }); }); - } - - // Queries Elasticsearch to obtain all the record level results for the specified job(s), time range, - // and record score threshold. - // Pass an empty array or ['*'] to search over all job IDs. - // Returned response contains a records property, which is an array of the matching results. - function getRecords(jobIds, threshold, earliestMs, latestMs, maxResults) { - return this.getRecordsForInfluencer(jobIds, [], threshold, earliestMs, latestMs, maxResults); - } - - // Queries Elasticsearch to obtain the record level results matching the given criteria, - // for the specified job(s), time range, and record score threshold. - // criteriaFields parameter must be an array, with each object in the array having 'fieldName' - // 'fieldValue' properties. - // Pass an empty array or ['*'] to search over all job IDs. - function getRecordsForCriteria(jobIds, criteriaFields, threshold, earliestMs, latestMs, maxResults) { - return $q((resolve, reject) => { - const obj = { success: true, records: [] }; - - // Build the criteria to use in the bool filter part of the request. - // Add criteria for the time range, record score, plus any specified job IDs. - const boolCriteria = [ - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: maxResults !== undefined ? maxResults : 100, + body: { + query: { + bool: { + filter: [ + { + query_string: { + query: 'result_type:record', + analyze_wildcard: false + } + }, + { + bool: { + must: boolCriteria + } + } + ] } }, - { - range: { - record_score: { - gte: threshold, - } - } + sort: [ + { record_score: { order: 'desc' } } + ], + } + }) + .then((resp) => { + if (resp.hits.total !== 0) { + _.each(resp.hits.hits, (hit) => { + obj.records.push(hit._source); + }); } - ]; + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); +} - if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { - let jobIdFilterStr = ''; - _.each(jobIds, (jobId, i) => { - if (i > 0) { - jobIdFilterStr += ' OR '; - } - jobIdFilterStr += 'job_id:'; - jobIdFilterStr += jobId; - }); - boolCriteria.push({ - query_string: { - analyze_wildcard: false, - query: jobIdFilterStr - } - }); + +// Queries Elasticsearch to obtain metric aggregation results. +// index can be a String, or String[], of index names to search. +// types must be a String[] of types to search. +// entityFields parameter must be an array, with each object in the array having 'fieldName' +// and 'fieldValue' properties. +// Extra query object can be supplied, or pass null if no additional query +// to that built from the supplied entity fields. +// Returned response contains a results property containing the requested aggregation. +function getMetricData( + index, + types, + entityFields, + query, + metricFunction, + metricFieldName, + timeFieldName, + earliestMs, + latestMs, + interval) { + return new Promise((resolve, reject) => { + const obj = { success: true, results: {} }; + + // Build the criteria to use in the bool filter part of the request. + // Add criteria for the types, time range, entity fields, + // plus any additional supplied query. + const mustCriteria = []; + const shouldCriteria = []; + + if (types && types.length) { + mustCriteria.push({ terms: { _type: types } }); + } + + mustCriteria.push({ + range: { + [timeFieldName]: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' + } } + }); - // Add in term queries for each of the specified criteria. - _.each(criteriaFields, (criteria) => { - boolCriteria.push({ + if (query) { + mustCriteria.push(query); + } + + _.each(entityFields, (entity) => { + if (entity.fieldValue.length !== 0) { + mustCriteria.push({ term: { - [criteria.fieldName]: criteria.fieldValue + [entity.fieldName]: entity.fieldValue } }); - }); - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: maxResults !== undefined ? maxResults : 100, - body: { - query: { - bool: { - filter: [ - { - query_string: { - query: 'result_type:record', - analyze_wildcard: false - } - }, - { - bool: { - must: boolCriteria - } + } else { + // Add special handling for blank entity field values, checking for either + // an empty string or the field not existing. + shouldCriteria.push({ + bool: { + must: [ + { + term: { + [entity.fieldName]: '' } - ] - } - }, - sort: [ - { record_score: { order: 'desc' } } - ], - } - }) - .then((resp) => { - if (resp.hits.total !== 0) { - _.each(resp.hits.hits, (hit) => { - obj.records.push(hit._source); - }); + } + ] + } + }); + shouldCriteria.push({ + bool: { + must_not: [ + { + exists: { field: entity.fieldName } + } + ] } - resolve(obj); - }) - .catch((resp) => { - reject(resp); }); - }); - } - - - // Queries Elasticsearch to obtain metric aggregation results. - // index can be a String, or String[], of index names to search. - // types must be a String[] of types to search. - // entityFields parameter must be an array, with each object in the array having 'fieldName' - // and 'fieldValue' properties. - // Extra query object can be supplied, or pass null if no additional query - // to that built from the supplied entity fields. - // Returned response contains a results property containing the requested aggregation. - function getMetricData( - index, - types, - entityFields, - query, - metricFunction, - metricFieldName, - timeFieldName, - earliestMs, - latestMs, - interval) { - return $q((resolve, reject) => { - const obj = { success: true, results: {} }; - - // Build the criteria to use in the bool filter part of the request. - // Add criteria for the types, time range, entity fields, - // plus any additional supplied query. - const mustCriteria = []; - const shouldCriteria = []; - - if (types && types.length) { - mustCriteria.push({ terms: { _type: types } }); } - mustCriteria.push({ - range: { - [timeFieldName]: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } + }); + + const body = { + query: { + bool: { + must: mustCriteria } - }); + }, + size: 0, + _source: { + excludes: [] + }, + aggs: { + byTime: { + date_histogram: { + field: timeFieldName, + interval: interval, + min_doc_count: 0 + } - if (query) { - mustCriteria.push(query); + } } + }; - _.each(entityFields, (entity) => { - if (entity.fieldValue.length !== 0) { - mustCriteria.push({ - term: { - [entity.fieldName]: entity.fieldValue - } - }); + if (shouldCriteria.length > 0) { + body.query.bool.should = shouldCriteria; + body.query.bool.minimum_should_match = shouldCriteria.length / 2; + } - } else { - // Add special handling for blank entity field values, checking for either - // an empty string or the field not existing. - shouldCriteria.push({ - bool: { - must: [ - { - term: { - [entity.fieldName]: '' - } - } - ] - } - }); - shouldCriteria.push({ - bool: { - must_not: [ - { - exists: { field: entity.fieldName } - } - ] - } - }); + if (metricFieldName !== undefined && metricFieldName !== '') { + body.aggs.byTime.aggs = {}; + + const metricAgg = { + [metricFunction]: { + field: metricFieldName } + }; + + if (metricFunction === 'percentiles') { + metricAgg[metricFunction].percents = [ML_MEDIAN_PERCENTS]; + } + body.aggs.byTime.aggs.metric = metricAgg; + } + + ml.esSearch({ + index, + body + }) + .then((resp) => { + const dataByTime = _.get(resp, ['aggregations', 'byTime', 'buckets'], []); + _.each(dataByTime, (dataForTime) => { + if (metricFunction === 'count') { + obj.results[dataForTime.key] = dataForTime.doc_count; + } else { + const value = _.get(dataForTime, ['metric', 'value']); + const values = _.get(dataForTime, ['metric', 'values']); + if (dataForTime.doc_count === 0) { + obj.results[dataForTime.key] = null; + } else if (value !== undefined) { + obj.results[dataForTime.key] = value; + } else if (values !== undefined) { + // Percentiles agg currently returns NaN rather than null when none of the docs in the + // bucket contain the field used in the aggregation + // (see elasticsearch issue https://github.com/elastic/elasticsearch/issues/29066). + // Store as null, so values can be handled in the same manner downstream as other aggs + // (min, mean, max) which return null. + const medianValues = values[ML_MEDIAN_PERCENTS]; + obj.results[dataForTime.key] = !isNaN(medianValues) ? medianValues : null; + } else { + obj.results[dataForTime.key] = null; + } + } + }); + resolve(obj); + }) + .catch((resp) => { + reject(resp); }); + }); +} + +// Queries Elasticsearch to obtain event rate data i.e. the count +// of documents over time. +// index can be a String, or String[], of index names to search. +// Extra query object can be supplied, or pass null if no additional query. +// Returned response contains a results property, which is an object +// of document counts against time (epoch millis). +function getEventRateData( + index, + query, + timeFieldName, + earliestMs, + latestMs, + interval) { + return new Promise((resolve, reject) => { + const obj = { success: true, results: {} }; + + // Build the criteria to use in the bool filter part of the request. + // Add criteria for the types, time range, entity fields, + // plus any additional supplied query. + const mustCriteria = [{ + range: { + [timeFieldName]: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' + } + } + }]; - const body = { + if (query) { + mustCriteria.push(query); + } + + ml.esSearch({ + index, + size: 0, + body: { query: { bool: { must: mustCriteria } }, - size: 0, _source: { excludes: [] }, aggs: { - byTime: { + eventRate: { date_histogram: { field: timeFieldName, interval: interval, - min_doc_count: 0 + min_doc_count: 0, + extended_bounds: { + min: earliestMs, + max: latestMs, + } } - } } - }; - - if (shouldCriteria.length > 0) { - body.query.bool.should = shouldCriteria; - body.query.bool.minimum_should_match = shouldCriteria.length / 2; - } - - if (metricFieldName !== undefined && metricFieldName !== '') { - body.aggs.byTime.aggs = {}; - - const metricAgg = { - [metricFunction]: { - field: metricFieldName - } - }; - - if (metricFunction === 'percentiles') { - metricAgg[metricFunction].percents = [ML_MEDIAN_PERCENTS]; - } - body.aggs.byTime.aggs.metric = metricAgg; } + }) + .then((resp) => { + const dataByTimeBucket = _.get(resp, ['aggregations', 'eventRate', 'buckets'], []); + _.each(dataByTimeBucket, (dataForTime) => { + const time = dataForTime.key; + obj.results[time] = dataForTime.doc_count; + }); + obj.total = resp.hits.total; - es.search({ - index, - body + resolve(obj); }) - .then((resp) => { - const dataByTime = _.get(resp, ['aggregations', 'byTime', 'buckets'], []); - _.each(dataByTime, (dataForTime) => { - if (metricFunction === 'count') { - obj.results[dataForTime.key] = dataForTime.doc_count; - } else { - const value = _.get(dataForTime, ['metric', 'value']); - const values = _.get(dataForTime, ['metric', 'values']); - if (dataForTime.doc_count === 0) { - obj.results[dataForTime.key] = null; - } else if (value !== undefined) { - obj.results[dataForTime.key] = value; - } else if (values !== undefined) { - // Percentiles agg currently returns NaN rather than null when none of the docs in the - // bucket contain the field used in the aggregation - // (see elasticsearch issue https://github.com/elastic/elasticsearch/issues/29066). - // Store as null, so values can be handled in the same manner downstream as other aggs - // (min, mean, max) which return null. - const medianValues = values[ML_MEDIAN_PERCENTS]; - obj.results[dataForTime.key] = !isNaN(medianValues) ? medianValues : null; - } else { - obj.results[dataForTime.key] = null; - } - } - }); + .catch((resp) => { + reject(resp); + }); + }); +} - resolve(obj); - }) - .catch((resp) => { - reject(resp); - }); - }); - } - - // Queries Elasticsearch to obtain event rate data i.e. the count - // of documents over time. - // index can be a String, or String[], of index names to search. - // Extra query object can be supplied, or pass null if no additional query. - // Returned response contains a results property, which is an object - // of document counts against time (epoch millis). - function getEventRateData( - index, - query, - timeFieldName, - earliestMs, - latestMs, - interval) { - return $q((resolve, reject) => { - const obj = { success: true, results: {} }; - - // Build the criteria to use in the bool filter part of the request. - // Add criteria for the types, time range, entity fields, - // plus any additional supplied query. - const mustCriteria = [{ +function getModelPlotOutput( + jobId, + detectorIndex, + criteriaFields, + earliestMs, + latestMs, + interval, + aggType) { + return new Promise((resolve, reject) => { + const obj = { + success: true, + results: {} + }; + + // if an aggType object has been passed in, use it. + // otherwise default to min and max aggs for the upper and lower bounds + const modelAggs = (aggType === undefined) ? + { max: 'max', min: 'min' } : + { + max: aggType.max, + min: aggType.min + }; + + // Build the criteria to use in the bool filter part of the request. + // Add criteria for the job ID and time range. + const mustCriteria = [ + { + term: { job_id: jobId } + }, + { range: { - [timeFieldName]: { + timestamp: { gte: earliestMs, lte: latestMs, format: 'epoch_millis' } } - }]; - - if (query) { - mustCriteria.push(query); } + ]; - es.search({ - index, - size: 0, - body: { - query: { - bool: { - must: mustCriteria + // Add in term queries for each of the specified criteria. + _.each(criteriaFields, (criteria) => { + mustCriteria.push({ + term: { + [criteria.fieldName]: criteria.fieldValue + } + }); + }); + + // Add criteria for the detector index. Results from jobs created before 6.1 will not + // contain a detector_index field, so use a should criteria with a 'not exists' check. + const shouldCriteria = [ + { + term: { detector_index: detectorIndex } + }, + { + bool: { + must_not: [ + { + exists: { field: 'detector_index' } } - }, - _source: { - excludes: [] - }, - aggs: { - eventRate: { - date_histogram: { - field: timeFieldName, - interval: interval, - min_doc_count: 0, - extended_bounds: { - min: earliestMs, - max: latestMs, + ] + } + } + ]; + + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: [{ + query_string: { + query: 'result_type:model_plot', + analyze_wildcard: true + } + }, { + bool: { + must: mustCriteria, + should: shouldCriteria, + minimum_should_match: 1 + } + }] + } + }, + aggs: { + times: { + date_histogram: { + field: 'timestamp', + interval: interval, + min_doc_count: 0 + }, + aggs: { + actual: { + avg: { + field: 'actual' + } + }, + modelUpper: { + [modelAggs.max]: { + field: 'model_upper' + } + }, + modelLower: { + [modelAggs.min]: { + field: 'model_lower' } } } } } - }) - .then((resp) => { - const dataByTimeBucket = _.get(resp, ['aggregations', 'eventRate', 'buckets'], []); - _.each(dataByTimeBucket, (dataForTime) => { - const time = dataForTime.key; - obj.results[time] = dataForTime.doc_count; - }); - obj.total = resp.hits.total; + } + }) + .then((resp) => { + const aggregationsByTime = _.get(resp, ['aggregations', 'times', 'buckets'], []); + _.each(aggregationsByTime, (dataForTime) => { + const time = dataForTime.key; + let modelUpper = _.get(dataForTime, ['modelUpper', 'value']); + let modelLower = _.get(dataForTime, ['modelLower', 'value']); + const actual = _.get(dataForTime, ['actual', 'value']); + + if (modelUpper === undefined || isFinite(modelUpper) === false) { + modelUpper = null; + } + if (modelLower === undefined || isFinite(modelLower) === false) { + modelLower = null; + } - resolve(obj); - }) - .catch((resp) => { - reject(resp); + obj.results[time] = { + actual, + modelUpper, + modelLower + }; }); - }); - } - - function getModelPlotOutput( - jobId, - detectorIndex, - criteriaFields, - earliestMs, - latestMs, - interval, - aggType) { - return $q((resolve, reject) => { - const obj = { - success: true, - results: {} - }; - // if an aggType object has been passed in, use it. - // otherwise default to min and max aggs for the upper and lower bounds - const modelAggs = (aggType === undefined) ? - { max: 'max', min: 'min' } : - { - max: aggType.max, - min: aggType.min - }; + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); +} - // Build the criteria to use in the bool filter part of the request. - // Add criteria for the job ID and time range. - const mustCriteria = [ - { - term: { job_id: jobId } - }, - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } +// Queries Elasticsearch to obtain the max record score over time for the specified job, +// criteria, time range, and aggregation interval. +// criteriaFields parameter must be an array, with each object in the array having 'fieldName' +// 'fieldValue' properties. +function getRecordMaxScoreByTime(jobId, criteriaFields, earliestMs, latestMs, interval) { + return new Promise((resolve, reject) => { + const obj = { + success: true, + results: {} + }; + + // Build the criteria to use in the bool filter part of the request. + const mustCriteria = [ + { + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' } } - ]; + }, + { term: { job_id: jobId } } + ]; + const shouldCriteria = []; - // Add in term queries for each of the specified criteria. - _.each(criteriaFields, (criteria) => { + _.each(criteriaFields, (criteria) => { + if (criteria.fieldValue.length !== 0) { mustCriteria.push({ term: { [criteria.fieldName]: criteria.fieldValue } }); - }); - - // Add criteria for the detector index. Results from jobs created before 6.1 will not - // contain a detector_index field, so use a should criteria with a 'not exists' check. - const shouldCriteria = [ - { - term: { detector_index: detectorIndex } - }, - { + } else { + // Add special handling for blank entity field values, checking for either + // an empty string or the field not existing. + const emptyFieldCondition = { bool: { - must_not: [ + must: [ { - exists: { field: 'detector_index' } + term: { + } } ] } - } - ]; - - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: [{ - query_string: { - query: 'result_type:model_plot', - analyze_wildcard: true - } - }, { - bool: { - must: mustCriteria, - should: shouldCriteria, - minimum_should_match: 1 - } - }] - } - }, - aggs: { - times: { - date_histogram: { - field: 'timestamp', - interval: interval, - min_doc_count: 0 - }, - aggs: { - actual: { - avg: { - field: 'actual' - } - }, - modelUpper: { - [modelAggs.max]: { - field: 'model_upper' - } - }, - modelLower: { - [modelAggs.min]: { - field: 'model_lower' - } - } + }; + emptyFieldCondition.bool.must[0].term[criteria.fieldName] = ''; + shouldCriteria.push(emptyFieldCondition); + shouldCriteria.push({ + bool: { + must_not: [ + { + exists: { field: criteria.fieldName } } - } + ] } - } - }) - .then((resp) => { - const aggregationsByTime = _.get(resp, ['aggregations', 'times', 'buckets'], []); - _.each(aggregationsByTime, (dataForTime) => { - const time = dataForTime.key; - let modelUpper = _.get(dataForTime, ['modelUpper', 'value']); - let modelLower = _.get(dataForTime, ['modelLower', 'value']); - const actual = _.get(dataForTime, ['actual', 'value']); - - if (modelUpper === undefined || isFinite(modelUpper) === false) { - modelUpper = null; - } - if (modelLower === undefined || isFinite(modelLower) === false) { - modelLower = null; - } - - obj.results[time] = { - actual, - modelUpper, - modelLower - }; - }); - - resolve(obj); - }) - .catch((resp) => { - reject(resp); }); + } + }); - } - - // Queries Elasticsearch to obtain the max record score over time for the specified job, - // criteria, time range, and aggregation interval. - // criteriaFields parameter must be an array, with each object in the array having 'fieldName' - // 'fieldValue' properties. - function getRecordMaxScoreByTime(jobId, criteriaFields, earliestMs, latestMs, interval) { - return $q((resolve, reject) => { - const obj = { - success: true, - results: {} - }; - // Build the criteria to use in the bool filter part of the request. - const mustCriteria = [ - { - range: { - timestamp: { - gte: earliestMs, - lte: latestMs, - format: 'epoch_millis' - } + ml.esSearch({ + index: ML_RESULTS_INDEX_PATTERN, + size: 0, + body: { + query: { + bool: { + filter: [{ + query_string: { + query: 'result_type:record', + analyze_wildcard: true + } + }, { + bool: { + must: mustCriteria + } + }] } }, - { term: { job_id: jobId } } - ]; - const shouldCriteria = []; - - _.each(criteriaFields, (criteria) => { - if (criteria.fieldValue.length !== 0) { - mustCriteria.push({ - term: { - [criteria.fieldName]: criteria.fieldValue - } - }); - } else { - // Add special handling for blank entity field values, checking for either - // an empty string or the field not existing. - const emptyFieldCondition = { - bool: { - must: [ - { - term: { - } - } - ] - } - }; - emptyFieldCondition.bool.must[0].term[criteria.fieldName] = ''; - shouldCriteria.push(emptyFieldCondition); - shouldCriteria.push({ - bool: { - must_not: [ - { - exists: { field: criteria.fieldName } - } - ] - } - }); - } - - }); - - es.search({ - index: ML_RESULTS_INDEX_PATTERN, - size: 0, - body: { - query: { - bool: { - filter: [{ - query_string: { - query: 'result_type:record', - analyze_wildcard: true - } - }, { - bool: { - must: mustCriteria - } - }] - } - }, - aggs: { - times: { - date_histogram: { - field: 'timestamp', - interval: interval, - min_doc_count: 1 - }, - aggs: { - recordScore: { - max: { - field: 'record_score' - } + aggs: { + times: { + date_histogram: { + field: 'timestamp', + interval: interval, + min_doc_count: 1 + }, + aggs: { + recordScore: { + max: { + field: 'record_score' } } } } } - }) - .then((resp) => { - const aggregationsByTime = _.get(resp, ['aggregations', 'times', 'buckets'], []); - _.each(aggregationsByTime, (dataForTime) => { - const time = dataForTime.key; - obj.results[time] = { - score: _.get(dataForTime, ['recordScore', 'value']), - }; - }); - - resolve(obj); - }) - .catch((resp) => { - reject(resp); + } + }) + .then((resp) => { + const aggregationsByTime = _.get(resp, ['aggregations', 'times', 'buckets'], []); + _.each(aggregationsByTime, (dataForTime) => { + const time = dataForTime.key; + obj.results[time] = { + score: _.get(dataForTime, ['recordScore', 'value']), + }; }); - }); - } - - return { - getScoresByBucket, - getScheduledEventsByBucket, - getTopInfluencers, - getTopInfluencerValues, - getOverallBucketScores, - getInfluencerValueMaxScoreByTime, - getCategoryDefinition, - getCategoryExamples, - getRecordInfluencers, - getRecordsForInfluencer, - getRecordsForDetector, - getRecords, - getRecordsForCriteria, - getMetricData, - getEventRateData, - getModelPlotOutput, - getRecordMaxScoreByTime - }; + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + }); } + +export const mlResultsService = { + getScoresByBucket, + getScheduledEventsByBucket, + getTopInfluencers, + getTopInfluencerValues, + getOverallBucketScores, + getInfluencerValueMaxScoreByTime, + getRecordInfluencers, + getRecordsForInfluencer, + getRecordsForDetector, + getRecords, + getRecordsForCriteria, + getMetricData, + getEventRateData, + getModelPlotOutput, + getRecordMaxScoreByTime +}; diff --git a/x-pack/plugins/ml/public/settings/scheduled_events/calendars_list/calendars_list_controller.js b/x-pack/plugins/ml/public/settings/scheduled_events/calendars_list/calendars_list_controller.js index 15279e6100ffcd..85d6242b20b529 100644 --- a/x-pack/plugins/ml/public/settings/scheduled_events/calendars_list/calendars_list_controller.js +++ b/x-pack/plugins/ml/public/settings/scheduled_events/calendars_list/calendars_list_controller.js @@ -18,6 +18,7 @@ import { checkGetJobsPrivilege, checkPermission } from 'plugins/ml/privilege/che import { getMlNodeCount, mlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; import { buttonsEnabledChecks } from 'plugins/ml/settings/scheduled_events/calendars_list/buttons_enabled_checks'; import { ml } from 'plugins/ml/services/ml_api_service'; +import { initPromise } from 'plugins/ml/util/promise'; import template from './calendars_list.html'; @@ -27,7 +28,8 @@ uiRoutes resolve: { CheckLicense: checkLicense, privileges: checkGetJobsPrivilege, - mlNodeCount: getMlNodeCount + mlNodeCount: getMlNodeCount, + initPromise: initPromise(true) } }); @@ -40,9 +42,7 @@ module.controller('MlCalendarsList', $filter, $route, $location, - $q, pagerFactory, - Private, timefilter, mlConfirmModalService) { @@ -117,7 +117,7 @@ module.controller('MlCalendarsList', title: `Delete calendar` }) .then(() => { - $q.when(ml.deleteCalendar({ calendarId })) + ml.deleteCalendar({ calendarId }) .then(loadCalendars) .catch((error) => { console.log(error); @@ -127,7 +127,7 @@ module.controller('MlCalendarsList', }; function loadCalendars() { - $q.when(ml.calendars()) + ml.calendars() .then((resp) => { calendars = resp; $scope.pager = pagerFactory.create(calendars.length, PAGE_SIZE, 1); diff --git a/x-pack/plugins/ml/public/settings/scheduled_events/components/import_events_modal/import_events_modal_controller.js b/x-pack/plugins/ml/public/settings/scheduled_events/components/import_events_modal/import_events_modal_controller.js index 1215014f4a6279..c4c63149a4c65f 100644 --- a/x-pack/plugins/ml/public/settings/scheduled_events/components/import_events_modal/import_events_modal_controller.js +++ b/x-pack/plugins/ml/public/settings/scheduled_events/components/import_events_modal/import_events_modal_controller.js @@ -17,7 +17,6 @@ const module = uiModules.get('apps/ml'); module.controller('MlImportEventsModal', function ( $scope, - $q, $timeout, $modalInstance) { @@ -67,7 +66,7 @@ module.controller('MlImportEventsModal', function ( }; function readFile(file) { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { $scope.loadingLock = true; if (file && file.size) { diff --git a/x-pack/plugins/ml/public/settings/scheduled_events/components/import_events_modal/import_events_service.js b/x-pack/plugins/ml/public/settings/scheduled_events/components/import_events_modal/import_events_service.js index 8a848f713c290f..58c49c66ce1606 100644 --- a/x-pack/plugins/ml/public/settings/scheduled_events/components/import_events_modal/import_events_service.js +++ b/x-pack/plugins/ml/public/settings/scheduled_events/components/import_events_modal/import_events_service.js @@ -11,10 +11,10 @@ import template from './import_events_modal.html'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); -module.service('mlImportEventsService', function ($q, $modal) { +module.service('mlImportEventsService', function ($modal) { this.openImportEventsWindow = function () { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { const modal = $modal.open({ template, controller: 'MlImportEventsModal', diff --git a/x-pack/plugins/ml/public/settings/scheduled_events/components/new_event_modal/new_event_service.js b/x-pack/plugins/ml/public/settings/scheduled_events/components/new_event_modal/new_event_service.js index c63b20155f4e98..3101fe2314a7dd 100644 --- a/x-pack/plugins/ml/public/settings/scheduled_events/components/new_event_modal/new_event_service.js +++ b/x-pack/plugins/ml/public/settings/scheduled_events/components/new_event_modal/new_event_service.js @@ -11,10 +11,10 @@ import template from './new_event_modal.html'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); -module.service('mlNewEventService', function ($q, $modal) { +module.service('mlNewEventService', function ($modal) { this.openNewEventWindow = function () { - return $q((resolve, reject) => { + return new Promise((resolve, reject) => { const modal = $modal.open({ template, controller: 'MlNewEventModal', diff --git a/x-pack/plugins/ml/public/settings/scheduled_events/new_calendar/create_calendar_controller.js b/x-pack/plugins/ml/public/settings/scheduled_events/new_calendar/create_calendar_controller.js index e5b9c81bd24c64..eaa0a471d711e6 100644 --- a/x-pack/plugins/ml/public/settings/scheduled_events/new_calendar/create_calendar_controller.js +++ b/x-pack/plugins/ml/public/settings/scheduled_events/new_calendar/create_calendar_controller.js @@ -18,9 +18,10 @@ import uiRoutes from 'ui/routes'; import { checkLicense } from 'plugins/ml/license/check_license'; import { checkGetJobsPrivilege } from 'plugins/ml/privilege/check_privilege'; import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; -import { CalendarServiceProvider } from 'plugins/ml/services/calendar_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; +import { mlCalendarService } from 'plugins/ml/services/calendar_service'; import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service'; +import { initPromise } from 'plugins/ml/util/promise'; import { ml } from 'plugins/ml/services/ml_api_service'; import template from './create_calendar.html'; @@ -31,7 +32,8 @@ uiRoutes resolve: { CheckLicense: checkLicense, privileges: checkGetJobsPrivilege, - checkMlNodesAvailable + checkMlNodesAvailable, + initPromise: initPromise(true) } }) .when('/settings/calendars_list/edit_calendar/:calendarId', { @@ -39,7 +41,8 @@ uiRoutes resolve: { CheckLicense: checkLicense, privileges: checkGetJobsPrivilege, - checkMlNodesAvailable + checkMlNodesAvailable, + initPromise: initPromise(true) } }); @@ -50,14 +53,9 @@ module.controller('MlCreateCalendar', function ( $scope, $route, - $location, - $q, - timefilter, - Private) { + $location) { const msgs = mlMessageBarService; msgs.clear(); - const mlJobService = Private(JobServiceProvider); - const mlCalendarService = Private(CalendarServiceProvider); const calendarId = $route.current.params.calendarId; $scope.isNewCalendar = (calendarId === undefined); @@ -142,7 +140,7 @@ module.controller('MlCreateCalendar', if (validateCalendarId(calendar.calendarId, $scope.validation.checks)) { $scope.saveLock = true; const saveFunc = $scope.isNewCalendar ? (c => ml.addCalendar(c)) : (c => ml.updateCalendar(c)); - $q.when(saveFunc(calendar)) + saveFunc(calendar) .then(() => { $location.path('settings/calendars_list'); $scope.saveLock = false; diff --git a/x-pack/plugins/ml/public/settings/settings_controller.js b/x-pack/plugins/ml/public/settings/settings_controller.js index 3ae63c6143052f..6d815542a2ab82 100644 --- a/x-pack/plugins/ml/public/settings/settings_controller.js +++ b/x-pack/plugins/ml/public/settings/settings_controller.js @@ -10,6 +10,7 @@ import uiRoutes from 'ui/routes'; import { checkLicense } from 'plugins/ml/license/check_license'; import { checkGetJobsPrivilege } from 'plugins/ml/privilege/check_privilege'; import { getMlNodeCount } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; +import { initPromise } from 'plugins/ml/util/promise'; import template from './settings.html'; @@ -19,7 +20,8 @@ uiRoutes resolve: { CheckLicense: checkLicense, privileges: checkGetJobsPrivilege, - mlNodeCount: getMlNodeCount + mlNodeCount: getMlNodeCount, + initPromise: initPromise(true) } }); diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/forecasting_modal/forecasting_modal.js b/x-pack/plugins/ml/public/timeseriesexplorer/forecasting_modal/forecasting_modal.js index 1bf8e455568ff2..bd7abd674a64e9 100644 --- a/x-pack/plugins/ml/public/timeseriesexplorer/forecasting_modal/forecasting_modal.js +++ b/x-pack/plugins/ml/public/timeseriesexplorer/forecasting_modal/forecasting_modal.js @@ -33,6 +33,8 @@ import { parseInterval } from '../../../common/util/parse_interval'; import { Modal } from './modal'; import { PROGRESS_STATES } from './progress_states'; import { ml } from 'plugins/ml/services/ml_api_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; +import { mlForecastService } from 'plugins/ml/services/forecast_service'; const FORECAST_JOB_MIN_VERSION = '6.1.0'; // Forecasting only allowed for jobs created >= 6.1.0. const FORECASTS_VIEW_MAX = 5; // Display links to a maximum of 5 forecasts. @@ -123,7 +125,7 @@ class ForecastingModal extends Component { jobOpeningState: PROGRESS_STATES.WAITING }); - this.props.mlJobService.openJob(this.props.job.job_id) + mlJobService.openJob(this.props.job.job_id) .then(() => { // If open was successful run the forecast, then close the job again. this.setState({ @@ -160,7 +162,7 @@ class ForecastingModal extends Component { // formats accepted by Kibana (w, M, y) are not valid formats in Elasticsearch. const durationInSeconds = parseInterval(this.state.newForecastDuration).asSeconds(); - this.props.mlForecastService.runForecast(this.props.job.job_id, `${durationInSeconds}s`) + mlForecastService.runForecast(this.props.job.job_id, `${durationInSeconds}s`) .then((resp) => { // Endpoint will return { acknowledged:true, id: } before forecast is complete. // So wait for results and then refresh the dashboard to the end of the forecast. @@ -180,7 +182,7 @@ class ForecastingModal extends Component { let previousProgress = 0; let noProgressMs = 0; this.forecastChecker = setInterval(() => { - this.props.mlForecastService.getForecastRequestStats(this.props.job, forecastId) + mlForecastService.getForecastRequestStats(this.props.job, forecastId) .then((resp) => { // Get the progress (stats value is between 0 and 1). const progress = _.get(resp, ['stats', 'forecast_progress'], previousProgress); @@ -198,7 +200,7 @@ class ForecastingModal extends Component { if (closeJobAfterRunning === true) { this.setState({ jobClosingState: PROGRESS_STATES.WAITING }); - this.props.mlJobService.closeJob(this.props.job.job_id) + mlJobService.closeJob(this.props.job.job_id) .then(() => { this.setState({ jobClosingState: PROGRESS_STATES.DONE @@ -263,7 +265,7 @@ class ForecastingModal extends Component { forecast_status: FORECAST_REQUEST_STATE.FINISHED } }; - this.props.mlForecastService.getForecastsSummary( + mlForecastService.getForecastsSummary( job, statusFinishedQuery, bounds.min.valueOf(), @@ -399,8 +401,6 @@ ForecastingModal.propTypes = { job: PropTypes.object, detectorIndex: PropTypes.number, entities: PropTypes.array, - mlForecastService: PropTypes.object.isRequired, - mlJobService: PropTypes.object.isRequired, loadForForecastId: PropTypes.func, }; diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/forecasting_modal/forecasting_modal_directive.js b/x-pack/plugins/ml/public/timeseriesexplorer/forecasting_modal/forecasting_modal_directive.js index 8b8f6c1356689a..9d5d1efe9b2403 100644 --- a/x-pack/plugins/ml/public/timeseriesexplorer/forecasting_modal/forecasting_modal_directive.js +++ b/x-pack/plugins/ml/public/timeseriesexplorer/forecasting_modal/forecasting_modal_directive.js @@ -10,24 +10,15 @@ import 'ngreact'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml', ['react']); -import { JobServiceProvider } from 'plugins/ml/services/job_service'; -import { ForecastServiceProvider } from 'plugins/ml/services/forecast_service'; import { ForecastingModal } from './forecasting_modal'; module.directive('mlForecastingModal', function ($injector) { - const Private = $injector.get('Private'); - const mlJobService = Private(JobServiceProvider); - const mlForecastService = Private(ForecastServiceProvider); const timefilter = $injector.get('timefilter'); const reactDirective = $injector.get('reactDirective'); return reactDirective( ForecastingModal, undefined, { restrict: 'E' }, - { - mlForecastService, - mlJobService, - timefilter - } + { timefilter } ); }); diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/timeseries_chart_directive.js b/x-pack/plugins/ml/public/timeseriesexplorer/timeseries_chart_directive.js index dee114edbbf11b..93f7797cfc9e6c 100644 --- a/x-pack/plugins/ml/public/timeseriesexplorer/timeseries_chart_directive.js +++ b/x-pack/plugins/ml/public/timeseriesexplorer/timeseries_chart_directive.js @@ -20,18 +20,19 @@ import 'ui/timefilter'; import { ResizeChecker } from 'ui/resize_checker'; -import { getSeverityWithLow } from 'plugins/ml/util/anomaly_utils'; +import { getSeverityWithLow } from 'plugins/ml/../common/util/anomaly_utils'; +import { formatValue } from 'plugins/ml/formatters/format_value'; import { drawLineChartDots, filterAxisLabels, numTicksForDateFormat } from 'plugins/ml/util/chart_utils'; import { TimeBuckets } from 'ui/time_buckets'; +import { mlAnomaliesTableService } from 'plugins/ml/components/anomalies_table/anomalies_table_service'; import ContextChartMask from 'plugins/ml/timeseriesexplorer/context_chart_mask'; import { findNearestChartPointToTime } from 'plugins/ml/timeseriesexplorer/timeseriesexplorer_utils'; -import 'plugins/ml/filters/format_value'; import { mlEscape } from 'plugins/ml/util/string_utils'; -import { FieldFormatServiceProvider } from 'plugins/ml/services/field_format_service'; +import { mlFieldFormatService } from 'plugins/ml/services/field_format_service'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); @@ -40,14 +41,11 @@ module.directive('mlTimeseriesChart', function ( $compile, $timeout, timefilter, - mlAnomaliesTableService, - formatValueFilter, Private, mlChartTooltipService) { function link(scope, element) { - const mlFieldFormatService = Private(FieldFormatServiceProvider); // Key dimensions for the viz and constituent charts. let svgWidth = angular.element('.results-container').width(); const focusZoomPanelHeight = 25; @@ -114,9 +112,9 @@ module.directive('mlTimeseriesChart', function ( drawContextChartSelection(); }); - scope.$on('renderFocusChart', () => { - renderFocusChart(); - }); + scope.$watchCollection('focusForecastData', renderFocusChart); + scope.$watchCollection('focusChartData', renderFocusChart); + scope.$watchGroup(['showModelBounds', 'showForecast'], renderFocusChart); // Redraw the charts when the container is resize. const resizeChecker = new ResizeChecker(angular.element('.ml-timeseries-chart')); @@ -969,10 +967,10 @@ module.directive('mlTimeseriesChart', function ( if (_.has(marker, 'actual')) { // Display the record actual in preference to the chart value, which may be // different depending on the aggregation interval of the chart. - contents += `actual: ${formatValueFilter(marker.actual, marker.function, fieldFormat)}`; - contents += `
typical: ${formatValueFilter(marker.typical, marker.function, fieldFormat)}`; + contents += `actual: ${formatValue(marker.actual, marker.function, fieldFormat)}`; + contents += `
typical: ${formatValue(marker.typical, marker.function, fieldFormat)}`; } else { - contents += `value: ${formatValueFilter(marker.value, marker.function, fieldFormat)}`; + contents += `value: ${formatValue(marker.value, marker.function, fieldFormat)}`; if (_.has(marker, 'byFieldName') && _.has(marker, 'numberOfCauses')) { const numberOfCauses = marker.numberOfCauses; const byFieldName = mlEscape(marker.byFieldName); @@ -986,21 +984,21 @@ module.directive('mlTimeseriesChart', function ( } } } else { - contents += `value: ${formatValueFilter(marker.value, marker.function, fieldFormat)}`; - contents += `
upper bounds: ${formatValueFilter(marker.upper, marker.function, fieldFormat)}`; - contents += `
lower bounds: ${formatValueFilter(marker.lower, marker.function, fieldFormat)}`; + contents += `value: ${formatValue(marker.value, marker.function, fieldFormat)}`; + contents += `
upper bounds: ${formatValue(marker.upper, marker.function, fieldFormat)}`; + contents += `
lower bounds: ${formatValue(marker.lower, marker.function, fieldFormat)}`; } } else { // TODO - need better formatting for small decimals. if (_.get(marker, 'isForecast', false) === true) { - contents += `prediction: ${formatValueFilter(marker.value, marker.function, fieldFormat)}`; + contents += `prediction: ${formatValue(marker.value, marker.function, fieldFormat)}`; } else { - contents += `value: ${formatValueFilter(marker.value, marker.function, fieldFormat)}`; + contents += `value: ${formatValue(marker.value, marker.function, fieldFormat)}`; } if (scope.modelPlotEnabled === true) { - contents += `
upper bounds: ${formatValueFilter(marker.upper, marker.function, fieldFormat)}`; - contents += `
lower bounds: ${formatValueFilter(marker.lower, marker.function, fieldFormat)}`; + contents += `
upper bounds: ${formatValue(marker.upper, marker.function, fieldFormat)}`; + contents += `
lower bounds: ${formatValue(marker.lower, marker.function, fieldFormat)}`; } } diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/timeseries_search_service.js b/x-pack/plugins/ml/public/timeseriesexplorer/timeseries_search_service.js index f244e7060f2fb9..54485016b51b82 100644 --- a/x-pack/plugins/ml/public/timeseriesexplorer/timeseries_search_service.js +++ b/x-pack/plugins/ml/public/timeseriesexplorer/timeseries_search_service.js @@ -11,149 +11,142 @@ import _ from 'lodash'; import { ml } from 'plugins/ml/services/ml_api_service'; import { isModelPlotEnabled } from 'plugins/ml/../common/util/job_utils'; import { buildConfigFromDetector } from 'plugins/ml/util/chart_config_builder'; -import { ResultsServiceProvider } from 'plugins/ml/services/results_service'; - -import { uiModules } from 'ui/modules'; -const module = uiModules.get('apps/ml'); - -module.service('mlTimeSeriesSearchService', function ( - $q, - Private) { - - const mlResultsService = Private(ResultsServiceProvider); - - this.getMetricData = function (job, detectorIndex, entityFields, earliestMs, latestMs, interval) { - if (isModelPlotEnabled(job, detectorIndex, entityFields)) { - // Extract the partition, by, over fields on which to filter. - const criteriaFields = []; - const detector = job.analysis_config.detectors[detectorIndex]; - if (_.has(detector, 'partition_field_name')) { - const partitionEntity = _.find(entityFields, { 'fieldName': detector.partition_field_name }); - if (partitionEntity !== undefined) { - criteriaFields.push( - { fieldName: 'partition_field_name', fieldValue: partitionEntity.fieldName }, - { fieldName: 'partition_field_value', fieldValue: partitionEntity.fieldValue }); - } +import { mlResultsService } from 'plugins/ml/services/results_service'; + +function getMetricData(job, detectorIndex, entityFields, earliestMs, latestMs, interval) { + if (isModelPlotEnabled(job, detectorIndex, entityFields)) { + // Extract the partition, by, over fields on which to filter. + const criteriaFields = []; + const detector = job.analysis_config.detectors[detectorIndex]; + if (_.has(detector, 'partition_field_name')) { + const partitionEntity = _.find(entityFields, { 'fieldName': detector.partition_field_name }); + if (partitionEntity !== undefined) { + criteriaFields.push( + { fieldName: 'partition_field_name', fieldValue: partitionEntity.fieldName }, + { fieldName: 'partition_field_value', fieldValue: partitionEntity.fieldValue }); } + } - if (_.has(detector, 'over_field_name')) { - const overEntity = _.find(entityFields, { 'fieldName': detector.over_field_name }); - if (overEntity !== undefined) { - criteriaFields.push( - { fieldName: 'over_field_name', fieldValue: overEntity.fieldName }, - { fieldName: 'over_field_value', fieldValue: overEntity.fieldValue }); - } + if (_.has(detector, 'over_field_name')) { + const overEntity = _.find(entityFields, { 'fieldName': detector.over_field_name }); + if (overEntity !== undefined) { + criteriaFields.push( + { fieldName: 'over_field_name', fieldValue: overEntity.fieldName }, + { fieldName: 'over_field_value', fieldValue: overEntity.fieldValue }); } + } - if (_.has(detector, 'by_field_name')) { - const byEntity = _.find(entityFields, { 'fieldName': detector.by_field_name }); - if (byEntity !== undefined) { - criteriaFields.push( - { fieldName: 'by_field_name', fieldValue: byEntity.fieldName }, - { fieldName: 'by_field_value', fieldValue: byEntity.fieldValue }); - } + if (_.has(detector, 'by_field_name')) { + const byEntity = _.find(entityFields, { 'fieldName': detector.by_field_name }); + if (byEntity !== undefined) { + criteriaFields.push( + { fieldName: 'by_field_name', fieldValue: byEntity.fieldName }, + { fieldName: 'by_field_value', fieldValue: byEntity.fieldValue }); } + } + + return mlResultsService.getModelPlotOutput( + job.job_id, + detectorIndex, + criteriaFields, + earliestMs, + latestMs, + interval + ); + } else { + return new Promise((resolve, reject) => { + const obj = { + success: true, + results: {} + }; - return mlResultsService.getModelPlotOutput( - job.job_id, - detectorIndex, - criteriaFields, + const chartConfig = buildConfigFromDetector(job, detectorIndex); + + mlResultsService.getMetricData( + chartConfig.datafeedConfig.indices, + chartConfig.datafeedConfig.types, + entityFields, + chartConfig.datafeedConfig.query, + chartConfig.metricFunction, + chartConfig.metricFieldName, + chartConfig.timeField, earliestMs, latestMs, interval - ); - } else { - return $q((resolve, reject) => { - const obj = { - success: true, - results: {} - }; - - const chartConfig = buildConfigFromDetector(job, detectorIndex); - - mlResultsService.getMetricData( - chartConfig.datafeedConfig.indices, - chartConfig.datafeedConfig.types, - entityFields, - chartConfig.datafeedConfig.query, - chartConfig.metricFunction, - chartConfig.metricFieldName, - chartConfig.timeField, - earliestMs, - latestMs, - interval - ) - .then((resp) => { - _.each(resp.results, (value, time) => { - obj.results[time] = { - 'actual': value - }; - }); - - resolve(obj); - }) - .catch((resp) => { - reject(resp); + ) + .then((resp) => { + _.each(resp.results, (value, time) => { + obj.results[time] = { + 'actual': value + }; }); - }); - } + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); - }; + }); + } +} + +// Builds chart detail information (charting function description and entity counts) used +// in the title area of the time series chart. +// Queries Elasticsearch if necessary to obtain the distinct count of entities +// for which data is being plotted. +function getChartDetails(job, detectorIndex, entityFields, earliestMs, latestMs) { + return new Promise((resolve, reject) => { + const obj = { success: true, results: { functionLabel: '', entityData: { entities: [] } } }; + + const chartConfig = buildConfigFromDetector(job, detectorIndex); + let functionLabel = chartConfig.metricFunction; + if (chartConfig.metricFieldName !== undefined) { + functionLabel += ' '; + functionLabel += chartConfig.metricFieldName; + } + obj.results.functionLabel = functionLabel; - // Builds chart detail information (charting function description and entity counts) used - // in the title area of the time series chart. - // Queries Elasticsearch if necessary to obtain the distinct count of entities - // for which data is being plotted. - this.getChartDetails = function (job, detectorIndex, entityFields, earliestMs, latestMs) { - return $q((resolve, reject) => { - const obj = { success: true, results: { functionLabel: '', entityData: { entities: [] } } }; + const blankEntityFields = _.filter(entityFields, (entity) => { + return entity.fieldValue.length === 0; + }); - const chartConfig = buildConfigFromDetector(job, detectorIndex); - let functionLabel = chartConfig.metricFunction; - if (chartConfig.metricFieldName !== undefined) { - functionLabel += ' '; - functionLabel += chartConfig.metricFieldName; - } - obj.results.functionLabel = functionLabel; - - const blankEntityFields = _.filter(entityFields, (entity) => { - return entity.fieldValue.length === 0; - }); - - // Look to see if any of the entity fields have defined values - // (i.e. blank input), and if so obtain the cardinality. - if (blankEntityFields.length === 0) { - obj.results.entityData.count = 1; - obj.results.entityData.entities = entityFields; - resolve(obj); - } else { - const entityFieldNames = _.map(blankEntityFields, 'fieldName'); - ml.getCardinalityOfFields({ - index: chartConfig.datafeedConfig.indices, - types: chartConfig.datafeedConfig.types, - fieldNames: entityFieldNames, - query: chartConfig.datafeedConfig.query, - timeFieldName: chartConfig.timeField, - earliestMs, - latestMs - }) - .then((results) => { - _.each(blankEntityFields, (field) => { - obj.results.entityData.entities.push({ - fieldName: field.fieldName, - cardinality: _.get(results, field.fieldName, 0) - }); + // Look to see if any of the entity fields have defined values + // (i.e. blank input), and if so obtain the cardinality. + if (blankEntityFields.length === 0) { + obj.results.entityData.count = 1; + obj.results.entityData.entities = entityFields; + resolve(obj); + } else { + const entityFieldNames = _.map(blankEntityFields, 'fieldName'); + ml.getCardinalityOfFields({ + index: chartConfig.datafeedConfig.indices, + types: chartConfig.datafeedConfig.types, + fieldNames: entityFieldNames, + query: chartConfig.datafeedConfig.query, + timeFieldName: chartConfig.timeField, + earliestMs, + latestMs + }) + .then((results) => { + _.each(blankEntityFields, (field) => { + obj.results.entityData.entities.push({ + fieldName: field.fieldName, + cardinality: _.get(results, field.fieldName, 0) }); - - resolve(obj); - }) - .catch((resp) => { - reject(resp); }); - } - }); - }; + resolve(obj); + }) + .catch((resp) => { + reject(resp); + }); + } + + }); +} -}); +export const mlTimeSeriesSearchService = { + getMetricData, + getChartDetails +}; diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.html b/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.html index 03b078b7535d80..a3549c52a0dfbe 100644 --- a/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.html +++ b/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.html @@ -127,10 +127,9 @@
- + table-data="tableData" + filter="filter" + />
diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_controller.js b/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_controller.js index ea02ab2894be83..19b51da3d65ee6 100644 --- a/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_controller.js +++ b/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_controller.js @@ -16,6 +16,7 @@ import _ from 'lodash'; import moment from 'moment'; import 'plugins/ml/components/anomalies_table'; +import 'plugins/ml/components/controls'; import { notify } from 'ui/notify'; import uiRoutes from 'ui/routes'; @@ -28,7 +29,7 @@ import { isTimeSeriesViewDetector, isModelPlotEnabled, mlFunctionToESAggregation } from 'plugins/ml/../common/util/job_utils'; -import { getIndexPatterns } from 'plugins/ml/util/index_utils'; +import { loadIndexPatterns, getIndexPatterns } from 'plugins/ml/util/index_utils'; import { createTimeSeriesJobData, processForecastResults, @@ -38,13 +39,16 @@ import { processScheduledEventsForChart } from 'plugins/ml/timeseriesexplorer/timeseriesexplorer_utils'; import { refreshIntervalWatcher } from 'plugins/ml/util/refresh_interval_watcher'; import { IntervalHelperProvider, getBoundsRoundedToInterval } from 'plugins/ml/util/ml_time_buckets'; -import { ResultsServiceProvider } from 'plugins/ml/services/results_service'; +import { mlResultsService } from 'plugins/ml/services/results_service'; import template from './timeseriesexplorer.html'; import { getMlNodeCount } from 'plugins/ml/ml_nodes_check/check_ml_nodes'; -import { JobServiceProvider } from 'plugins/ml/services/job_service'; -import { FieldFormatServiceProvider } from 'plugins/ml/services/field_format_service'; -import { ForecastServiceProvider } from 'plugins/ml/services/forecast_service'; +import { ml } from 'plugins/ml/services/ml_api_service'; +import { mlJobService } from 'plugins/ml/services/job_service'; +import { mlFieldFormatService } from 'plugins/ml/services/field_format_service'; import { JobSelectServiceProvider } from 'plugins/ml/components/job_select_list/job_select_service'; +import { mlForecastService } from 'plugins/ml/services/forecast_service'; +import { mlTimeSeriesSearchService } from 'plugins/ml/timeseriesexplorer/timeseries_search_service'; +import { initPromise } from 'plugins/ml/util/promise'; uiRoutes .when('/timeseriesexplorer/?', { @@ -52,8 +56,9 @@ uiRoutes resolve: { CheckLicense: checkLicense, privileges: checkGetJobsPrivilege, - indexPatterns: getIndexPatterns, - mlNodeCount: getMlNodeCount + indexPatterns: loadIndexPatterns, + mlNodeCount: getMlNodeCount, + initPromise: initPromise(true) } }); @@ -67,8 +72,8 @@ module.controller('MlTimeSeriesExplorerController', function ( Private, timefilter, AppState, - mlTimeSeriesSearchService, - mlAnomaliesTableService) { + mlSelectIntervalService, + mlSelectSeverityService) { $scope.timeFieldName = 'timestamp'; timefilter.enableTimeRangeSelector(); @@ -78,10 +83,6 @@ module.controller('MlTimeSeriesExplorerController', function ( const ANOMALIES_MAX_RESULTS = 500; const MAX_SCHEDULED_EVENTS = 10; // Max number of scheduled events displayed per bucket. const TimeBuckets = Private(IntervalHelperProvider); - const mlResultsService = Private(ResultsServiceProvider); - const mlJobService = Private(JobServiceProvider); - const mlFieldFormatService = Private(FieldFormatServiceProvider); - const mlForecastService = Private(ForecastServiceProvider); const mlJobSelectService = Private(JobSelectServiceProvider); $scope.jobPickerSelections = []; @@ -90,6 +91,7 @@ module.controller('MlTimeSeriesExplorerController', function ( $scope.loading = true; $scope.loadCounter = 0; $scope.hasResults = false; + $scope.anomalyRecords = []; $scope.modelPlotEnabled = false; $scope.showModelBounds = true; // Toggles display of model bounds in the focus chart @@ -342,33 +344,38 @@ module.controller('MlTimeSeriesExplorerController', function ( $scope.refreshFocusData = function (fromDate, toDate) { - // Counter to keep track of what data sets have been loaded. + // Counter to keep track of the queries to populate the chart. let awaitingCount = 3; + // This object is used to store the results of individual remote requests + // before we transform it into the final data and apply it to $scope. Otherwise + // we might trigger multiple $digest cycles and depending on how deep $watches + // listen for changes we could miss updates. + const refreshFocusData = {}; + // finish() function, called after each data set has been loaded and processed. // The last one to call it will trigger the page render. function finish() { awaitingCount--; if (awaitingCount === 0) { - processDataForFocusAnomalies( - $scope.focusChartData, - $scope.anomalyRecords, + // Tell the results container directives to render the focus chart. + refreshFocusData.focusChartData = processDataForFocusAnomalies( + refreshFocusData.focusChartData, + refreshFocusData.anomalyRecords, $scope.timeFieldName); - processScheduledEventsForChart( - $scope.focusChartData, - $scope.scheduledEvents); + refreshFocusData.focusChartData = processScheduledEventsForChart( + refreshFocusData.focusChartData, + refreshFocusData.scheduledEvents); - console.log('Time series explorer focus chart data set:', $scope.focusChartData); - - // Tell the results container directives to render the focus chart. - // Need to use $timeout to ensure the broadcast happens after the child scope is updated with the new data. - $timeout(() => { - $scope.$broadcast('renderFocusChart'); - $scope.$broadcast('renderTable'); + // All the data is ready now for a scope update. + // Use $evalAsync to ensure the update happens after the child scope is updated with the new data. + $scope.$evalAsync(() => { + $scope = Object.assign($scope, refreshFocusData); + console.log('Time series explorer focus chart data set:', $scope.focusChartData); $scope.loading = false; - }, 0); + }); } } @@ -393,15 +400,15 @@ module.controller('MlTimeSeriesExplorerController', function ( searchBounds.max.valueOf(), $scope.focusAggregationInterval.expression ).then((resp) => { - $scope.focusChartData = processMetricPlotResults(resp.results, $scope.modelPlotEnabled); + refreshFocusData.focusChartData = processMetricPlotResults(resp.results, $scope.modelPlotEnabled); $scope.showModelBoundsCheckbox = ($scope.modelPlotEnabled === true) && - ($scope.focusChartData.length > 0); + (refreshFocusData.focusChartData.length > 0); finish(); }).catch((resp) => { console.log('Time series explorer - error getting metric data from elasticsearch:', resp); }); - // Query 2 - load records across selected time range. + // Query 2 - load all the records across selected time range for the chart anomaly markers. mlResultsService.getRecordsForCriteria( [$scope.selectedJob.job_id], $scope.criteriaFields, @@ -411,11 +418,11 @@ module.controller('MlTimeSeriesExplorerController', function ( ANOMALIES_MAX_RESULTS ).then((resp) => { // Sort in descending time order before storing in scope. - $scope.anomalyRecords = _.chain(resp.records) + refreshFocusData.anomalyRecords = _.chain(resp.records) .sortBy(record => record[$scope.timeFieldName]) .reverse() .value(); - console.log('Time series explorer anomalies:', $scope.anomalyRecords); + console.log('Time series explorer anomalies:', refreshFocusData.anomalyRecords); finish(); }); @@ -428,7 +435,7 @@ module.controller('MlTimeSeriesExplorerController', function ( 1, MAX_SCHEDULED_EVENTS ).then((resp) => { - $scope.scheduledEvents = resp.events[$scope.selectedJob.job_id]; + refreshFocusData.scheduledEvents = resp.events[$scope.selectedJob.job_id]; finish(); }).catch((resp) => { console.log('Time series explorer - error getting scheduled events from elasticsearch:', resp); @@ -455,14 +462,17 @@ module.controller('MlTimeSeriesExplorerController', function ( $scope.focusAggregationInterval.expression, aggType) .then((resp) => { - $scope.focusForecastData = processForecastResults(resp.results); - $scope.showForecastCheckbox = ($scope.focusForecastData.length > 0); + refreshFocusData.focusForecastData = processForecastResults(resp.results); + refreshFocusData.showForecastCheckbox = (refreshFocusData.focusForecastData.length > 0); finish(); }).catch((resp) => { console.log(`Time series explorer - error loading data for forecast ID ${forecastId}`, resp); }); } + // Load the data for the anomalies table. + loadAnomaliesTableData(searchBounds.min.valueOf(), searchBounds.max.valueOf()); + }; $scope.saveSeriesPropertiesAndRefresh = function () { @@ -476,6 +486,19 @@ module.controller('MlTimeSeriesExplorerController', function ( $scope.refresh(); }; + $scope.filter = function (field, value, operator) { + const entity = _.find($scope.entities, { fieldName: field }); + if (entity !== undefined) { + if (operator === '+' && entity.fieldValue !== value) { + entity.fieldValue = value; + $scope.saveSeriesPropertiesAndRefresh(); + } else if (operator === '-' && entity.fieldValue === value) { + entity.fieldValue = ''; + $scope.saveSeriesPropertiesAndRefresh(); + } + } + }; + $scope.loadForForecastId = function (forecastId) { mlForecastService.getForecastDateRange( $scope.selectedJob, @@ -524,16 +547,14 @@ module.controller('MlTimeSeriesExplorerController', function ( }; $scope.toggleShowModelBounds = function () { - $scope.showModelBounds = !$scope.showModelBounds; $timeout(() => { - $scope.$broadcast('renderFocusChart'); + $scope.showModelBounds = !$scope.showModelBounds; }, 0); }; $scope.toggleShowForecast = function () { - $scope.showForecast = !$scope.showForecast; $timeout(() => { - $scope.$broadcast('renderFocusChart'); + $scope.showForecast = !$scope.showForecast; }, 0); }; @@ -546,28 +567,23 @@ module.controller('MlTimeSeriesExplorerController', function ( $scope.refresh(); }); - // Add a listener for filter changes triggered from the anomalies table. - const filterChangeListener = function (field, value, operator) { - const entity = _.find($scope.entities, { fieldName: field }); - if (entity !== undefined) { - if (operator === '+' && entity.fieldValue !== value) { - entity.fieldValue = value; - $scope.saveSeriesPropertiesAndRefresh(); - } else if (operator === '-' && entity.fieldValue === value) { - entity.fieldValue = ''; - $scope.saveSeriesPropertiesAndRefresh(); - } + // Reload the anomalies table if the Interval or Threshold controls are changed. + const tableControlsListener = function () { + if ($scope.zoomFrom !== undefined && $scope.zoomTo !== undefined) { + loadAnomaliesTableData($scope.zoomFrom.getTime(), $scope.zoomTo.getTime()); } }; + mlSelectIntervalService.state.watch(tableControlsListener); + mlSelectSeverityService.state.watch(tableControlsListener); - mlAnomaliesTableService.filterChange.watch(filterChangeListener); $scope.$on('$destroy', () => { refreshWatcher.cancel(); - mlAnomaliesTableService.filterChange.unwatch(filterChangeListener); + mlSelectIntervalService.state.unwatch(tableControlsListener); + mlSelectSeverityService.state.unwatch(tableControlsListener); }); - // When inside a dashboard in the ML plugin, listen for changes to job selection. + // Listen for changes to job selection. mlJobSelectService.listenJobSelectionChange($scope, (event, selections) => { // Clear the detectorIndex, entities and forecast info. if (selections.length > 0) { @@ -655,7 +671,7 @@ module.controller('MlTimeSeriesExplorerController', function ( updateControlsForDetector(); // Populate the map of jobs / detectors / field formatters for the selected IDs and refresh. - mlFieldFormatService.populateFormats([jobId], $route.current.locals.indexPatterns) + mlFieldFormatService.populateFormats([jobId], getIndexPatterns()) .finally(() => { // Load the data - if the FieldFormats failed to populate // the default formatting will be used for metric values. @@ -663,6 +679,49 @@ module.controller('MlTimeSeriesExplorerController', function ( }); } + function loadAnomaliesTableData(earliestMs, latestMs) { + ml.results.getAnomaliesTableData( + [$scope.selectedJob.job_id], + $scope.criteriaFields, + [], + mlSelectIntervalService.state.get('interval').val, + mlSelectSeverityService.state.get('threshold').val, + earliestMs, + latestMs, + ANOMALIES_MAX_RESULTS + ).then((resp) => { + const anomalies = resp.anomalies; + const detectorsByJob = mlJobService.detectorsByJob; + anomalies.forEach((anomaly) => { + // Add a detector property to each anomaly. + // Default to functionDescription if no description available. + // TODO - when job_service is moved server_side, move this to server endpoint. + const jobId = anomaly.jobId; + anomaly.detector = _.get(detectorsByJob, + [jobId, anomaly.detectorIndex, 'detector_description'], + anomaly.source.function_description); + + // Add properties used for building the links menu. + // TODO - when job_service is moved server_side, move this to server endpoint. + if (_.has(mlJobService.customUrlsByJob, jobId)) { + anomaly.customUrls = mlJobService.customUrlsByJob[jobId]; + } + }); + + $scope.$evalAsync(() => { + $scope.tableData = { + anomalies, + interval: resp.interval, + examplesByJobId: resp.examplesByJobId, + showViewSeriesLink: false + }; + }); + + }).catch((resp) => { + console.log('Time series explorer - error loading data for anomalies table:', resp); + }); + } + function updateControlsForDetector() { // Update the entity dropdown control(s) according to the partitioning fields for the selected detector. const detectorIndex = +$scope.detectorId; diff --git a/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_utils.js b/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_utils.js index a4761d172ac0e9..c59d5e1c86041a 100644 --- a/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_utils.js +++ b/x-pack/plugins/ml/public/timeseriesexplorer/timeseriesexplorer_utils.js @@ -107,9 +107,9 @@ export function processDataForFocusAnomalies( const recordTime = record[timeFieldName]; let chartPoint = findNearestChartPointToTime(chartData, recordTime); - // TODO - handle case where there is an anomaly due to the absense of data + // TODO - handle case where there is an anomaly due to the absence of data // and there is no model plot. - if (chartPoint === undefined && chartData.length) { + if (chartPoint === undefined && chartData !== undefined && chartData.length) { // In case there is a record with a time after that of the last chart point, set the score // for the last chart point to that of the last record, if that record has a higher score. const lastChartPoint = chartData[chartData.length - 1]; @@ -167,6 +167,10 @@ export function processScheduledEventsForChart(chartData, scheduledEvents) { export function findNearestChartPointToTime(chartData, time) { let chartPoint; + if(chartData === undefined) { + return chartPoint; + } + for (let i = 0; i < chartData.length; i++) { if (chartData[i].date.getTime() === time) { chartPoint = chartData[i]; diff --git a/x-pack/plugins/ml/public/util/index_utils.js b/x-pack/plugins/ml/public/util/index_utils.js index 8b0c755fcf3fbb..e0a669dfab4c1a 100644 --- a/x-pack/plugins/ml/public/util/index_utils.js +++ b/x-pack/plugins/ml/public/util/index_utils.js @@ -9,31 +9,58 @@ import { notify } from 'ui/notify'; import { SavedObjectsClientProvider } from 'ui/saved_objects'; -export function getIndexPatterns(Private) { +let indexPatterns = []; +let fullIndexPatterns = []; +let currentIndexPattern = null; +let currentSavedSearch = null; + +export function loadIndexPatterns(Private, courier) { + fullIndexPatterns = courier.indexPatterns; const savedObjectsClient = Private(SavedObjectsClientProvider); return savedObjectsClient.find({ type: 'index-pattern', fields: ['title'], perPage: 10000 - }).then(response => response.savedObjects); + }).then((response) => { + indexPatterns = response.savedObjects; + return indexPatterns; + }); +} + +export function getIndexPatterns() { + return indexPatterns; +} + +export function getIndexPatternIdFromName(name) { + for (let j = 0; j < indexPatterns.length; j++) { + if (indexPatterns[j].get('title') === name) { + return indexPatterns[j].id; + } + } + return name; +} + +export function loadCurrentIndexPattern(courier, $route) { + fullIndexPatterns = courier.indexPatterns; + currentIndexPattern = fullIndexPatterns.get($route.current.params.index); + return currentIndexPattern; } -export function getIndexPattern(courier, indexPatternId) { - return courier.indexPatterns.get(indexPatternId); +export function getIndexPatternById(id) { + return fullIndexPatterns.get(id); } -export function getIndexPatternWithRoute(courier, $route) { - return getIndexPattern(courier, $route.current.params.index); +export function loadCurrentSavedSearch(courier, $route, savedSearches) { + currentSavedSearch = savedSearches.get($route.current.params.savedSearchId); + return currentSavedSearch; } -export function getIndexPatternProvider(courier) { - return function (indexPatternId) { - return getIndexPattern(courier, indexPatternId); - }; +export function getCurrentIndexPattern() { + return currentIndexPattern; } -export function getSavedSearchWithRoute(courier, $route, savedSearches) { - return savedSearches.get($route.current.params.savedSearchId); +export function getCurrentSavedSearch() { + return currentSavedSearch; } // returns true if the index passed in is time based diff --git a/x-pack/plugins/ml/public/util/promise.js b/x-pack/plugins/ml/public/util/promise.js new file mode 100644 index 00000000000000..3d59d300079da5 --- /dev/null +++ b/x-pack/plugins/ml/public/util/promise.js @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// to work around the need for wrapping all of our promises in $q for our angular code +// we replace the native Promise with $q. +// For pages which are mainly react, initPromise should be called with false +// and any calls to promises in angular code wrapped in $q.when +// once we're free of angular this file can be removed. + +const promise = window.Promise; + +export function initPromise(replacePromise) { + return function ($q) { + window.Promise = replacePromise ? $q : promise; + return Promise.resolve(); + }; +} diff --git a/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.js b/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.js index a298b032c52407..2415a391da5338 100644 --- a/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.js +++ b/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.js @@ -75,11 +75,11 @@ export function calculateModelMemoryLimitProvider(callWithRequest) { let mmlKB = 0; if (i === 0) { // first in the list is the basic calculation. - // a base of 10MB plus 32KB per series per detector - // i.e. 10000KB + (32KB * cardinality of split field * number or detectors) + // a base of 10MB plus 64KB per series per detector + // i.e. 10000KB + (64KB * cardinality of split field * number or detectors) const cardinality = resp[splitFieldName]; mmlKB = 10000; - const SERIES_MULTIPLIER = 32; + const SERIES_MULTIPLIER = 64; const numberOfFields = fieldNames.length; if (cardinality !== undefined) { @@ -110,7 +110,7 @@ export function calculateModelMemoryLimitProvider(callWithRequest) { mmlMB = (maxBytes / numeral('1MB').value()); } } - response(`${mmlMB}MB`); + response({ modelMemoryLimit: `${mmlMB}MB` }); }) .catch((error) => { reject(error); diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js index 7ceada4264287c..0c3d9988d76b8f 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.js @@ -105,6 +105,10 @@ export class DataRecognizer { } async searchForFields(moduleConfig, indexPattern) { + if (moduleConfig.query === undefined) { + return false; + } + const index = indexPattern; const size = 0; const body = { @@ -158,21 +162,23 @@ export class DataRecognizer { })); // load all of the kibana saved objects - const kKeys = Object.keys(manifestJSON.kibana); - await Promise.all(kKeys.map(async (key) => { - kibana[key] = []; - await Promise.all(manifestJSON.kibana[key].map(async (obj) => { - const kConfig = await this.readFile(`${this.modulesDir}/${dirName}/${KIBANA_DIR}/${key}/${obj.file}`); - // use the file name for the id - const kId = obj.file.replace('.json', ''); - const config = JSON.parse(kConfig); - kibana[key].push({ - id: kId, - title: config.title, - config - }); + if (manifestJSON.kibana !== undefined) { + const kKeys = Object.keys(manifestJSON.kibana); + await Promise.all(kKeys.map(async (key) => { + kibana[key] = []; + await Promise.all(manifestJSON.kibana[key].map(async (obj) => { + const kConfig = await this.readFile(`${this.modulesDir}/${dirName}/${KIBANA_DIR}/${key}/${obj.file}`); + // use the file name for the id + const kId = obj.file.replace('.json', ''); + const config = JSON.parse(kConfig); + kibana[key].push({ + id: kId, + title: config.title, + config + }); + })); })); - })); + } return { jobs, @@ -185,7 +191,17 @@ export class DataRecognizer { // takes a module config id, an optional jobPrefix and the request object // creates all of the jobs, datafeeds and savedObjects listed in the module config. // if any of the savedObjects already exist, they will not be overwritten. - async setupModuleItems(moduleId, jobPrefix, groups, indexPatternName, query, request) { + async setupModuleItems( + moduleId, + jobPrefix, + groups, + indexPatternName, + query, + startDatafeed, + start, + end, + request + ) { this.savedObjectsClient = request.getSavedObjectsClient(); this.indexPatterns = await this.loadIndexPatterns(); @@ -229,6 +245,24 @@ export class DataRecognizer { }); } saveResults.datafeeds = await this.saveDatafeeds(moduleConfig.datafeeds); + + if (startDatafeed) { + const savedDatafeeds = moduleConfig.datafeeds.filter((df) => { + const datafeedResult = saveResults.datafeeds.find(d => d.id === df.id); + return (datafeedResult !== undefined && datafeedResult.success === true); + }); + + const startResults = await this.startDatafeeds(savedDatafeeds, start, end); + saveResults.datafeeds.forEach((df) => { + const startedDatafeed = startResults[df.id]; + if (startedDatafeed !== undefined) { + df.started = startedDatafeed.started; + if (startedDatafeed.error !== undefined) { + df.error = startedDatafeed.error; + } + } + }); + } } // create the savedObjects @@ -361,14 +395,11 @@ export class DataRecognizer { // as success: false async saveDatafeeds(datafeeds) { return await Promise.all(datafeeds.map(async (datafeed) => { - const datafeedId = datafeed.id; - try { - datafeed.id = datafeedId; await this.saveDatafeed(datafeed); - return { id: datafeedId, success: true }; + return { id: datafeed.id, success: true, started: false }; } catch (error) { - return { id: datafeedId, success: false, error }; + return { id: datafeed.id, success: false, started: false, error }; } })); } @@ -378,6 +409,51 @@ export class DataRecognizer { return this.callWithRequest('ml.addDatafeed', { datafeedId, body }); } + async startDatafeeds(datafeeds, start, end) { + const results = {}; + for (const datafeed of datafeeds) { + results[datafeed.id] = await this.startDatafeed(datafeed, start, end); + } + return results; + } + + async startDatafeed(datafeed, start, end) { + const result = { started: false }; + let opened = false; + try { + const openResult = await this.callWithRequest('ml.openJob', { jobId: datafeed.config.job_id }); + opened = openResult.opened; + } catch (error) { + // if the job is already open, a 409 will be returned. + if (error.statusCode === 409) { + opened = true; + } else { + opened = false; + result.started = false; + result.error = error; + } + } + if (opened) { + try { + const duration = { start: 0 }; + if (start !== undefined) { + duration.start = start; + } + if (end !== undefined) { + duration.end = end; + } + + await this.callWithRequest('ml.startDatafeed', { datafeedId: datafeed.id, ...duration }); + result.started = true; + } catch (error) { + result.started = false; + result.error = error; + } + } + return result; + } + + // merge all of the save results into one result object // which is returned from the endpoint async updateResults(results, saveResults) { @@ -398,6 +474,7 @@ export class DataRecognizer { saveResults.datafeeds.forEach((d2) => { if (d.id === d2.id) { d.success = d2.success; + d.started = d2.started; if (d2.error !== undefined) { d.error = d2.error; } diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/logo.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/logo.json new file mode 100644 index 00000000000000..88cff79a5b5805 --- /dev/null +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/logo.json @@ -0,0 +1,5 @@ +{ + "src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAlCAYAAAAjt+tHAAADMUlEQVRYhe2XTWhUVxSAv/Nm3jSVRB3SJtCMZhhpky4LguCiug2FbnRRBFeKGxFEEBSXCl2VLMSdhS7qJuhCC9JVIQUXrloItLbUxPyaxJ9kUIOTO/NOF/fe9zMThHQGp4vczZt77rnvfPeen3dGVFXp4gi6afx/AZAHuLn4hDurixTzhS2VIrKka/VNjg0McXqo3D7At9OPuDL/D6EKRsSZA1VBJAkPu57Mf6mu86xW43JlpC0A2T15X19pI2VE3FIUGw1V4g2bfqMoRXK8ODLWFkBwIXWNRhRVJXSJYecSGzWiFABxkOdLZdodoqp6fe4xt1cXKeZDVEHEO8JRuqePhWrdcHywxNl9lc4AtP2WNkbX07DrAPlmwWsTcW/2DYJgfaOAuCeA4BPFOk8REbwjRcB6NdHzul8P76I3zJ45EwN/Vw0nJleZ36jTUCUnYNxaoGTmIeJ07DOSRMeDAhiUELvvwId5bh0d4LM9ScHL4Hw3tcb0holf7F8SpnQCTYy7sxGJlUViDRtnuKFKoNBwe2Y26oxPVTM3kAEY7rOmcoIzYI00lAyQ1ZEmmTemMWTkliKxQDkR9vdmvd6ShhcePueHmdfxyY07dZTyp5+nb8Y0yf085wKhocrJSi/jhz56NwDAWi0iEUscgzbA0oGWVEWwsvQ8lrt7Kn7QmnQ7hailDgC8MJsE2Nqf+gKjYolV7W9xz/5w6z7iPwGc+/N3bqwuZGTNvQExnh0jhR6+//wLDu/t3zZAJgauTT/i6txjgLgP8E1Ic29gJBs6oQi1L7/aNkAmBp683QBs0xG6PkBTBtVBpKFwOkaVpc237QFcHP6UkUIPItaQiL16D5G4IYihvHy8PMonhZ5tA7Sk4atGnbsrS2Ra0eZIhGRdlNFduzm4p7ht41sCvO/R9TrQdYAtC1E7Y2J5kR+XZxGfIdLa1K4bw7HBEuf2VzoLMLEyzzd/TbmPUrZwhZqkr6rw68wfvDS1zgbh2G8P+Lm6Hhv3tcSncoFsgeuTXGdj4MxQGWmqln4uqdP7calU6Xwa/vRsiVtPFwhSfYH3faQQiP1ze/zjIU6Vyjt1YAeAfwEhypX7ku7g2QAAAABJRU5ErkJggg==", + "height": 25, + "width": 120 +} diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json new file mode 100644 index 00000000000000..b505d54fdd414c --- /dev/null +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json @@ -0,0 +1,37 @@ +{ + "id": "apm_transaction", + "title": "APM", + "description": "Detect anomalies in high mean of transaction duration", + "type": "Transaction data", + "logoFile": "logo.json", + "defaultIndexPattern": "apm-*", + "query": { + "bool": { + "filter": [ + { + "term": { + "processor.name": "transaction" + } + }, + { + "term": { + "processor.event": "transaction" + } + } + ] + } + }, + "jobs": [ + { + "id": "high_mean_response_time", + "file": "high_mean_response_time.json" + } + ], + "datafeeds": [ + { + "id": "datafeed-high_mean_response_time", + "file": "datafeed_high_mean_response_time.json", + "job_id": "high_mean_response_time" + } + ] +} diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_response_time.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_response_time.json new file mode 100644 index 00000000000000..69d5a8651a8fe3 --- /dev/null +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_response_time.json @@ -0,0 +1,25 @@ +{ + "job_id": "JOB_ID", + "indexes": [ + "INDEX_PATTERN_NAME" + ], + "types": [], + "query": { + "match": { + "processor.event": { + "query": "transaction", + "operator": "OR", + "prefix_length": 0, + "max_expansions": 50, + "fuzzy_transpositions": true, + "lenient": false, + "zero_terms_query": "NONE", + "auto_generate_synonyms_phrase_query": true, + "boost": 1 + } + } + }, + "chunking_config": { + "mode": "auto" + } +} diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json new file mode 100644 index 00000000000000..98aebd32d31af1 --- /dev/null +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_response_time.json @@ -0,0 +1,29 @@ +{ + "job_type": "anomaly_detector", + "groups": [ + "apm" + ], + "description": "Detect anomalies in high mean of transaction duration", + "analysis_config": { + "bucket_span": "15m", + "detectors": [ + { + "detector_description": "high_mean(\"transaction.duration.us\")", + "function": "high_mean", + "field_name": "transaction.duration.us", + "rules": [] + } + ], + "influencers": [] + }, + "analysis_limits": { + "model_memory_limit": "10mb" + }, + "data_description": { + "time_field": "@timestamp" + }, + "model_plot_config": { + "enabled": true + }, + "model_snapshot_retention_days": 1 +} diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js index b85f4f76c5c143..94c43fb1054a77 100644 --- a/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js +++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/job_validation.js @@ -285,8 +285,7 @@ describe('ML - validateJob', () => { 'job_id_valid', 'detectors_function_not_empty', 'index_fields_valid', - 'time_field_invalid', - 'success_mml' + 'time_field_invalid' ]); } ); diff --git a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js index 782d7d34027ad9..c069618bcd9415 100644 --- a/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js +++ b/x-pack/plugins/ml/server/models/job_validation/__tests__/validate_model_memory_limit.js @@ -25,7 +25,7 @@ describe('ML - validateModelMemoryLimit', () => { } }, limits: { - max_model_memory_limit: '20mb' + max_model_memory_limit: '30mb' } }; @@ -103,7 +103,7 @@ describe('ML - validateModelMemoryLimit', () => { return validateModelMemoryLimit(callWithRequest, job, duration).then( (messages) => { const ids = messages.map(m => m.id); - expect(ids).to.eql(['success_mml']); + expect(ids).to.eql([]); } ); }); @@ -111,7 +111,7 @@ describe('ML - validateModelMemoryLimit', () => { it('Called with no duration or split and mml above limit', () => { const job = getJobConfig(); const duration = undefined; - job.analysis_limits.model_memory_limit = '21mb'; + job.analysis_limits.model_memory_limit = '31mb'; return validateModelMemoryLimit(callWithRequest, job, duration).then( (messages) => { @@ -139,7 +139,7 @@ describe('ML - validateModelMemoryLimit', () => { const dtrs = createDetectors(2); const job = getJobConfig(['instance'], dtrs); const duration = { start: 0, end: 1 }; - job.analysis_limits.model_memory_limit = '20mb'; + job.analysis_limits.model_memory_limit = '30mb'; return validateModelMemoryLimit(callWithRequest, job, duration).then( (messages) => { @@ -192,4 +192,32 @@ describe('ML - validateModelMemoryLimit', () => { ); }); + it('Called with specified invalid mml of "0mb"', () => { + const dtrs = createDetectors(1); + const job = getJobConfig(['instance'], dtrs); + const duration = { start: 0, end: 1 }; + job.analysis_limits.model_memory_limit = '0mb'; + + return validateModelMemoryLimit(callWithRequest, job, duration).then( + (messages) => { + const ids = messages.map(m => m.id); + expect(ids).to.eql(['mml_value_invalid']); + } + ); + }); + + it('Called with specified invalid mml of "asdf"', () => { + const dtrs = createDetectors(1); + const job = getJobConfig(['instance'], dtrs); + const duration = { start: 0, end: 1 }; + job.analysis_limits.model_memory_limit = 'asdf'; + + return validateModelMemoryLimit(callWithRequest, job, duration).then( + (messages) => { + const ids = messages.map(m => m.id); + expect(ids).to.eql(['mml_value_invalid']); + } + ); + }); + }); diff --git a/x-pack/plugins/ml/server/models/job_validation/messages.json b/x-pack/plugins/ml/server/models/job_validation/messages.json index 8ff6f363ee8ba8..7f3fec66ffcc08 100644 --- a/x-pack/plugins/ml/server/models/job_validation/messages.json +++ b/x-pack/plugins/ml/server/models/job_validation/messages.json @@ -151,6 +151,10 @@ "status": "ERROR", "text": "The model memory limit is greater than the max model memory limit configured for this cluster." }, + "mml_value_invalid": { + "status": "ERROR", + "text": "{{mml}} is not a valid value for model memory limit. The value should be specified in bytes e.g. 10MB" + }, "estimated_mml_greater_than_mml": { "status": "INFO", "text": "The estimated model memory limit is greater than the model memory limit you have configured." diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.js b/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.js index 748f0dc970b27d..90896bed5c9700 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.js +++ b/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.js @@ -73,7 +73,7 @@ export async function validateModelMemoryLimit(callWithRequest, job, duration) { duration.start, duration.end, true); - const mmlEstimateBytes = numeral(mmlEstimate).value(); + const mmlEstimateBytes = numeral(mmlEstimate.modelMemoryLimit).value(); let runEstimateGreaterThenMml = true; // if max_model_memory_limit has been set, @@ -96,7 +96,12 @@ export async function validateModelMemoryLimit(callWithRequest, job, duration) { // the max mml if (runEstimateGreaterThenMml && mml !== null) { const mmlBytes = numeral(mml).value(); - if (mmlEstimateBytes > mmlBytes) { + if (mmlBytes === 0) { + messages.push({ + id: 'mml_value_invalid', + mml + }); + } else if (mmlEstimateBytes > mmlBytes) { messages.push({ id: 'estimated_mml_greater_than_mml', maxModelMemoryLimit, @@ -120,7 +125,7 @@ export async function validateModelMemoryLimit(callWithRequest, job, duration) { } } - if (messages.length === 0) { + if (messages.length === 0 && runCalcModelMemoryTest === true) { messages.push({ id: 'success_mml' }); } diff --git a/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.js b/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.js new file mode 100644 index 00000000000000..e1755f136dec60 --- /dev/null +++ b/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.js @@ -0,0 +1,192 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + +import _ from 'lodash'; +import moment from 'moment'; + +import { + getEntityFieldName, + getEntityFieldValue, + showActualForFunction, + showTypicalForFunction +} from '../../../common/util/anomaly_utils'; + + +// Builds the items for display in the anomalies table from the supplied list of anomaly records. +export function buildAnomalyTableItems(anomalyRecords, aggregationInterval) { + + // Aggregate the anomaly records if necessary, and create skeleton display records with + // time, detector (description) and source record properties set. + let displayRecords = []; + if (aggregationInterval !== 'second') { + displayRecords = aggregateAnomalies(anomalyRecords, aggregationInterval); + } else { + // Show all anomaly records. + displayRecords = anomalyRecords.map((record) => { + return { + time: record.timestamp, + source: record, + }; + }); + } + + // Fill out the remaining properties in each display record + // for the columns to be displayed in the table. + const time = (new Date()).getTime(); + return displayRecords.map((record, index) => { + const source = record.source; + const jobId = source.job_id; + + // Identify each row with a unique ID which is used by the table for row expansion. + record.rowId = `${time}_${index}`; + + record.jobId = jobId; + record.detectorIndex = source.detector_index; + record.severity = source.record_score; + + const entityName = getEntityFieldName(source); + if (entityName !== undefined) { + record.entityName = entityName; + record.entityValue = getEntityFieldValue(source); + } + + if (source.influencers !== undefined) { + const influencers = []; + const sourceInfluencers = _.sortBy(source.influencers, 'influencer_field_name'); + sourceInfluencers.forEach((influencer) => { + const influencerFieldName = influencer.influencer_field_name; + influencer.influencer_field_values.forEach((influencerFieldValue) => { + influencers.push({ + [influencerFieldName]: influencerFieldValue + }); + }); + }); + record.influencers = influencers; + } + + // Add fields to the display records for the actual and typical values. + // To ensure sorting in the EuiTable works correctly, add extra 'sort' + // properties which are single numeric values rather than the underlying arrays. + // These properties can be removed if EuiTable sorting logic can be customized + // - see https://github.com/elastic/eui/issues/425 + const functionDescription = source.function_description || ''; + const causes = source.causes || []; + if (showActualForFunction(functionDescription) === true) { + if (source.actual !== undefined) { + record.actual = source.actual; + record.actualSort = getMetricSortValue(source.actual); + } else { + // If only a single cause, copy values to the top level. + if (causes.length === 1) { + record.actual = causes[0].actual; + record.actualSort = getMetricSortValue(causes[0].actual); + } + } + } + if (showTypicalForFunction(functionDescription) === true) { + if (source.typical !== undefined) { + record.typical = source.typical; + record.typicalSort = getMetricSortValue(source.typical); + } else { + // If only a single cause, copy values to the top level. + if (causes.length === 1) { + record.typical = causes[0].typical; + record.typicalSort = getMetricSortValue(causes[0].typical); + } + } + } + + // Add a sortable property for the magnitude of the factor by + // which the actual value is different from the typical. + if (Array.isArray(record.actual) && record.actual.length === 1 && + Array.isArray(record.typical) && record.typical.length === 1) { + const actualVal = Number(record.actual[0]); + const typicalVal = Number(record.typical[0]); + record.metricDescriptionSort = (actualVal > typicalVal) ? + actualVal / typicalVal : typicalVal / actualVal; + } + + return record; + + }); +} + +function aggregateAnomalies(anomalyRecords, interval) { + // Aggregate the anomaly records by time, jobId, detectorIndex, and entity (by/over/partition). + // anomalyRecords assumed to be supplied in ascending time order. + if (anomalyRecords.length === 0) { + return []; + } + + const aggregatedData = {}; + anomalyRecords.forEach((record) => { + // Use moment.js to get start of interval. + const roundedTime = moment(record.timestamp).startOf(interval).valueOf(); + if (aggregatedData[roundedTime] === undefined) { + aggregatedData[roundedTime] = {}; + } + + // Aggregate by job, then detectorIndex. + const jobId = record.job_id; + const jobsAtTime = aggregatedData[roundedTime]; + if (jobsAtTime[jobId] === undefined) { + jobsAtTime[jobId] = {}; + } + + // Aggregate by detector - default to function_description if no description available. + const detectorIndex = record.detector_index; + const detectorsForJob = jobsAtTime[jobId]; + if (detectorsForJob[detectorIndex] === undefined) { + detectorsForJob[detectorIndex] = {}; + } + + // Now add an object for the anomaly with the highest anomaly score per entity. + // For the choice of entity, look in order for byField, overField, partitionField. + // If no by/over/partition, default to an empty String. + const entitiesForDetector = detectorsForJob[detectorIndex]; + + // TODO - are we worried about different byFields having the same + // value e.g. host=server1 and machine=server1? + let entity = getEntityFieldValue(record); + if (entity === undefined) { + entity = ''; + } + if (entitiesForDetector[entity] === undefined) { + entitiesForDetector[entity] = record; + } else { + if (record.record_score > entitiesForDetector[entity].record_score) { + entitiesForDetector[entity] = record; + } + } + }); + + // Flatten the aggregatedData to give a list of records with + // the highest score per bucketed time / jobId / detectorIndex. + const summaryRecords = []; + _.each(aggregatedData, (times, roundedTime) => { + _.each(times, (jobIds) => { + _.each(jobIds, (entityDetectors) => { + _.each(entityDetectors, (record) => { + summaryRecords.push({ + time: +roundedTime, + source: record + }); + }); + }); + }); + }); + + return summaryRecords; + +} + +function getMetricSortValue(value) { + // Returns a sortable value for a metric field (actual and typical values) + // from the supplied value, which for metric functions will be a single + // valued array. + return (Array.isArray(value) && value.length > 0) ? value[0] : value; +} diff --git a/x-pack/dev-tools/functional_tests/index.js b/x-pack/plugins/ml/server/models/results_service/index.js similarity index 72% rename from x-pack/dev-tools/functional_tests/index.js rename to x-pack/plugins/ml/server/models/results_service/index.js index 6eba9bc3361bf6..995e9a06f63265 100644 --- a/x-pack/dev-tools/functional_tests/index.js +++ b/x-pack/plugins/ml/server/models/results_service/index.js @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -export { - runFunctionTests, - runApiTests, - runFunctionalTestsServer, -} from './tasks'; + + +export { resultsServiceProvider } from './results_service'; diff --git a/x-pack/plugins/ml/server/models/results_service/results_service.js b/x-pack/plugins/ml/server/models/results_service/results_service.js new file mode 100644 index 00000000000000..7b569c26009a5e --- /dev/null +++ b/x-pack/plugins/ml/server/models/results_service/results_service.js @@ -0,0 +1,268 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + + +import _ from 'lodash'; +import moment from 'moment'; + +import { buildAnomalyTableItems } from './build_anomaly_table_items'; +import { ML_RESULTS_INDEX_PATTERN } from '../../../common/constants/index_patterns'; + + +// Service for carrying out Elasticsearch queries to obtain data for the +// ML Results dashboards. + +const DEFAULT_QUERY_SIZE = 500; +const DEFAULT_MAX_EXAMPLES = 500; + +export function resultsServiceProvider(callWithRequest) { + + // Obtains data for the anomalies table, aggregating anomalies by day or hour as requested. + // Return an Object with properties 'anomalies' and 'interval' (interval used to aggregate anomalies, + // one of day, hour or second. Note 'auto' can be provided as the aggregationInterval in the request, + // in which case the interval is determined according to the time span between the first and + // last anomalies), plus an examplesByJobId property if any of the + // anomalies are categorization anomalies in mlcategory. + async function getAnomaliesTableData( + jobIds, + criteriaFields, + influencers, + aggregationInterval, + threshold, + earliestMs, + latestMs, + maxRecords = DEFAULT_QUERY_SIZE, + maxExamples = DEFAULT_MAX_EXAMPLES) { + + // Build the query to return the matching anomaly record results. + // Add criteria for the time range, record score, plus any specified job IDs. + const boolCriteria = [ + { + range: { + timestamp: { + gte: earliestMs, + lte: latestMs, + format: 'epoch_millis' + } + } + }, + { + range: { + record_score: { + gte: threshold, + } + } + } + ]; + + if (jobIds && jobIds.length > 0 && !(jobIds.length === 1 && jobIds[0] === '*')) { + let jobIdFilterStr = ''; + jobIds.forEach((jobId, i) => { + if (i > 0) { + jobIdFilterStr += ' OR '; + } + jobIdFilterStr += 'job_id:'; + jobIdFilterStr += jobId; + }); + boolCriteria.push({ + query_string: { + analyze_wildcard: false, + query: jobIdFilterStr + } + }); + } + + // Add in term queries for each of the specified criteria. + criteriaFields.forEach((criteria) => { + boolCriteria.push({ + term: { + [criteria.fieldName]: criteria.fieldValue + } + }); + }); + + // Add a nested query to filter for each of the specified influencers. + if (influencers.length > 0) { + boolCriteria.push({ + bool: { + should: influencers.map((influencer) => { + return { + nested: { + path: 'influencers', + query: { + bool: { + must: [ + { + match: { + 'influencers.influencer_field_name': influencer.fieldName + } + }, + { + match: { + 'influencers.influencer_field_values': influencer.fieldValue + } + } + ] + } + } + } + }; + }), + minimum_should_match: 1, + } + }); + } + + const resp = await callWithRequest('search', { + index: ML_RESULTS_INDEX_PATTERN, + size: maxRecords, + body: { + query: { + bool: { + filter: [ + { + query_string: { + query: 'result_type:record', + analyze_wildcard: false + } + }, + { + bool: { + must: boolCriteria + } + } + ] + } + }, + sort: [ + { record_score: { order: 'desc' } } + ] + } + }); + + const tableData = { anomalies: [], interval: 'second' }; + if (resp.hits.total !== 0) { + let records = []; + resp.hits.hits.forEach((hit) => { + records.push(hit._source); + }); + + // Sort anomalies in ascending time order. + records = _.sortBy(records, 'timestamp'); + tableData.interval = aggregationInterval; + if (aggregationInterval === 'auto') { + // Determine the actual interval to use if aggregating. + const earliest = moment(records[0].timestamp); + const latest = moment(records[records.length - 1].timestamp); + + const daysDiff = latest.diff(earliest, 'days'); + tableData.interval = (daysDiff < 2 ? 'hour' : 'day'); + } + + tableData.anomalies = buildAnomalyTableItems(records, tableData.interval); + + // Load examples for any categorization anomalies. + const categoryAnomalies = tableData.anomalies.filter(item => item.entityName === 'mlcategory'); + if (categoryAnomalies.length > 0) { + tableData.examplesByJobId = {}; + + const categoryIdsByJobId = {}; + categoryAnomalies.forEach((anomaly) => { + if (!_.has(categoryIdsByJobId, anomaly.jobId)) { + categoryIdsByJobId[anomaly.jobId] = []; + } + if (categoryIdsByJobId[anomaly.jobId].indexOf(anomaly.entityValue) === -1) { + categoryIdsByJobId[anomaly.jobId].push(anomaly.entityValue); + } + }); + + const categoryJobIds = Object.keys(categoryIdsByJobId); + await Promise.all(categoryJobIds.map(async (jobId) => { + const examplesByCategoryId = await getCategoryExamples(jobId, categoryIdsByJobId[jobId], maxExamples); + tableData.examplesByJobId[jobId] = examplesByCategoryId; + })); + } + + } + + return tableData; + + } + + + // Obtains the categorization examples for the categories with the specified IDs + // from the given index and job ID. + // Returned response consists of a list of examples against category ID. + async function getCategoryExamples(jobId, categoryIds, maxExamples) { + const resp = await callWithRequest('search', { + index: ML_RESULTS_INDEX_PATTERN, + size: DEFAULT_QUERY_SIZE, // Matches size of records in anomaly summary table. + body: { + query: { + bool: { + filter: [ + { term: { job_id: jobId } }, + { terms: { category_id: categoryIds } } + ] + } + } + } + }); + + const examplesByCategoryId = {}; + if (resp.hits.total !== 0) { + resp.hits.hits.forEach((hit) => { + if (maxExamples) { + examplesByCategoryId[hit._source.category_id] = + _.slice(hit._source.examples, 0, Math.min(hit._source.examples.length, maxExamples)); + } else { + examplesByCategoryId[hit._source.category_id] = hit._source.examples; + } + }); + } + + return examplesByCategoryId; + } + + // Obtains the definition of the category with the specified ID and job ID. + // Returned response contains four properties - categoryId, regex, examples + // and terms (space delimited String of the common tokens matched in values of the category). + async function getCategoryDefinition(jobId, categoryId) { + const resp = await callWithRequest('search', { + index: ML_RESULTS_INDEX_PATTERN, + size: 1, + body: { + query: { + bool: { + filter: [ + { term: { job_id: jobId } }, + { term: { category_id: categoryId } } + ] + } + } + } + }); + + const definition = { categoryId, terms: null, regex: null, examples: [] }; + if (resp.hits.total !== 0) { + const source = resp.hits.hits[0]._source; + definition.categoryId = source.category_id; + definition.regex = source.regex; + definition.terms = source.terms; + definition.examples = source.examples; + } + + return definition; + } + + return { + getAnomaliesTableData, + getCategoryDefinition, + getCategoryExamples + }; + +} diff --git a/x-pack/plugins/ml/server/routes/modules.js b/x-pack/plugins/ml/server/routes/modules.js index 3eb883a8dd9f1b..bae0e4b6fcbcbe 100644 --- a/x-pack/plugins/ml/server/routes/modules.js +++ b/x-pack/plugins/ml/server/routes/modules.js @@ -21,9 +21,29 @@ function getModule(callWithRequest, moduleId) { return dr.getModule(moduleId); } -function saveModuleItems(callWithRequest, moduleId, prefix, groups, indexPatternName, query, request) { +function saveModuleItems( + callWithRequest, + moduleId, + prefix, + groups, + indexPatternName, + query, + startDatafeed, + start, + end, + request +) { const dr = new DataRecognizer(callWithRequest); - return dr.setupModuleItems(moduleId, prefix, groups, indexPatternName, query, request); + return dr.setupModuleItems( + moduleId, + prefix, + groups, + indexPatternName, + query, + startDatafeed, + start, + end, + request); } export function dataRecognizer(server, commonRouteConfig) { @@ -69,10 +89,24 @@ export function dataRecognizer(server, commonRouteConfig) { prefix, groups, indexPatternName, - query + query, + startDatafeed, + start, + end } = request.payload; - return saveModuleItems(callWithRequest, moduleId, prefix, groups, indexPatternName, query, request) + return saveModuleItems( + callWithRequest, + moduleId, + prefix, + groups, + indexPatternName, + query, + startDatafeed, + start, + end, + request + ) .then(resp => reply(resp)) .catch(resp => reply(wrapError(resp))); }, diff --git a/x-pack/plugins/ml/server/routes/results_service.js b/x-pack/plugins/ml/server/routes/results_service.js new file mode 100644 index 00000000000000..07f261a07e0f1e --- /dev/null +++ b/x-pack/plugins/ml/server/routes/results_service.js @@ -0,0 +1,101 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + + +import { callWithRequestFactory } from '../client/call_with_request_factory'; +import { wrapError } from '../client/errors'; +import { resultsServiceProvider } from '../models/results_service'; + + +function getAnomaliesTableData(callWithRequest, payload) { + const rs = resultsServiceProvider(callWithRequest); + const { + jobIds, + criteriaFields, + influencers, + aggregationInterval, + threshold, + earliestMs, + latestMs, + maxRecords, + maxExamples } = payload; + return rs.getAnomaliesTableData( + jobIds, + criteriaFields, + influencers, + aggregationInterval, + threshold, + earliestMs, + latestMs, + maxRecords, + maxExamples); +} + +function getCategoryDefinition(callWithRequest, payload) { + const rs = resultsServiceProvider(callWithRequest); + return rs.getCategoryDefinition( + payload.jobId, + payload.categoryId); +} + +function getCategoryExamples(callWithRequest, payload) { + const rs = resultsServiceProvider(callWithRequest); + const { + jobId, + categoryIds, + maxExamples } = payload; + return rs.getCategoryExamples( + jobId, + categoryIds, + maxExamples); +} + +export function resultsServiceRoutes(server, commonRouteConfig) { + + server.route({ + method: 'POST', + path: '/api/ml/results/anomalies_table_data', + handler(request, reply) { + const callWithRequest = callWithRequestFactory(server, request); + return getAnomaliesTableData(callWithRequest, request.payload) + .then(resp => reply(resp)) + .catch(resp => reply(wrapError(resp))); + }, + config: { + ...commonRouteConfig + } + }); + + server.route({ + method: 'POST', + path: '/api/ml/results/category_definition', + handler(request, reply) { + const callWithRequest = callWithRequestFactory(server, request); + return getCategoryDefinition(callWithRequest, request.payload) + .then(resp => reply(resp)) + .catch(resp => reply(wrapError(resp))); + }, + config: { + ...commonRouteConfig + } + }); + + server.route({ + method: 'POST', + path: '/api/ml/results/category_examples', + handler(request, reply) { + const callWithRequest = callWithRequestFactory(server, request); + return getCategoryExamples(callWithRequest, request.payload) + .then(resp => reply(resp)) + .catch(resp => reply(wrapError(resp))); + }, + config: { + ...commonRouteConfig + } + }); + +} diff --git a/x-pack/plugins/ml/server/routes/system.js b/x-pack/plugins/ml/server/routes/system.js index 615358dbdeb3e1..6889fa80b172ae 100644 --- a/x-pack/plugins/ml/server/routes/system.js +++ b/x-pack/plugins/ml/server/routes/system.js @@ -125,4 +125,18 @@ export function systemRoutes(server, commonRouteConfig) { ...commonRouteConfig } }); + + server.route({ + method: 'POST', + path: '/api/ml/es_search', + handler(request, reply) { + const callWithRequest = callWithRequestFactory(server, request); + return callWithRequest('search', request.payload) + .then(resp => reply(resp)) + .catch(resp => reply(wrapError(resp))); + }, + config: { + ...commonRouteConfig + } + }); } diff --git a/x-pack/plugins/monitoring/common/constants.js b/x-pack/plugins/monitoring/common/constants.js index 6b015234ce63cc..e1f1806026b1a2 100644 --- a/x-pack/plugins/monitoring/common/constants.js +++ b/x-pack/plugins/monitoring/common/constants.js @@ -33,11 +33,6 @@ export const KIBANA_SETTINGS_TYPE = 'kibana_settings'; * @type {string} */ export const KIBANA_USAGE_TYPE = 'kibana'; -/** - * The type name used within the Monitoring index to publish reporting stats. - * @type {string} - */ -export const KIBANA_REPORTING_TYPE = 'reporting_stats'; /* * Key for the localStorage service diff --git a/x-pack/plugins/monitoring/init.js b/x-pack/plugins/monitoring/init.js index 55d4b9bf72fcce..c948a537dd8c67 100644 --- a/x-pack/plugins/monitoring/init.js +++ b/x-pack/plugins/monitoring/init.js @@ -7,49 +7,39 @@ import { requireUIRoutes } from './server/routes'; import { instantiateClient } from './server/es_client/instantiate_client'; import { initMonitoringXpackInfo } from './server/init_monitoring_xpack_info'; -import { initKibanaMonitoring } from './server/kibana_monitoring'; +import { createCollectorSet } from './server/kibana_monitoring'; /** - * Initialize the Kibana Monitoring plugin by starting up asynchronous server - * tasks, based on user-defined configuration - * - webserver route handling - * - monitoring cluster health checker - * - instantiation of an elasticsearch-js client exposed as a server plugin object - * - start kibana ops monitoring loop - * - start monitoring cluster x-pack license and features check loop + * Initialize the Kibana Monitoring plugin by starting up asynchronous server tasks + * - [1] instantiation of an elasticsearch-js client exposed as a server plugin object + * - [2] start monitoring cluster x-pack license and features check + * - [3] webserver route handling + * - [4] start the internal monitoring collectors + * - [5] expose the monitoring collector object for other plugins to register with + * - [6] set monitoring plugin status to green * @param monitoringPlugin {Object} Monitoring UI plugin * @param server {Object} HapiJS server instance */ export const init = (monitoringPlugin, server) => { + monitoringPlugin.status.yellow('Initializing'); const xpackMainPlugin = server.plugins.xpack_main; xpackMainPlugin.status.once('green', async () => { const config = server.config(); const uiEnabled = config.get('xpack.monitoring.ui.enabled'); - const features = []; - const onceMonitoringGreen = callbackFn => monitoringPlugin.status.once('green', () => callbackFn()); // avoid race condition in things that require ES client if (uiEnabled) { - // Instantiate the dedicated ES client - features.push(instantiateClient(server)); - - // route handlers depend on xpackInfo (exposed as server.plugins.monitoring.info) - onceMonitoringGreen(async () => { - await initMonitoringXpackInfo(server); - }); - - // Require only routes needed for ui app - features.push(requireUIRoutes(server)); + await instantiateClient(server); // Instantiate the dedicated ES client + await initMonitoringXpackInfo(server); // Route handlers depend on this for xpackInfo + await requireUIRoutes(server); } - // Send Kibana usage / server ops to the monitoring bulk api if (config.get('xpack.monitoring.kibana.collection.enabled')) { - onceMonitoringGreen(() => { - features.push(initKibanaMonitoring(monitoringPlugin.kbnServer, server)); - }); + const collectorSet = createCollectorSet(monitoringPlugin.kbnServer, server); // instantiate an object for collecting/sending metrics and usage stats + server.expose('collectorSet', collectorSet); // expose the collector set object on the server. other plugins will call statsCollectors.register(collector) to define their own collection } - Promise.all(features); + monitoringPlugin.status.green('Ready'); }); server.injectUiAppVars('monitoring', (server) => { diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js b/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js index 7401a5c6364977..f3c6f6e8d31735 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js @@ -89,7 +89,7 @@ export function ElasticsearchPanel(props) { Version - { get(nodes, 'versions[0]') || 'N/A' } + { props.version || 'N/A' } Uptime diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/helpers.js b/x-pack/plugins/monitoring/public/components/cluster/overview/helpers.js index ff8ddec368197a..c0e3a6a6b28e4c 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/helpers.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/helpers.js @@ -49,7 +49,7 @@ const PanelExtras = ({ extras }) => { export function ClusterItemContainer(props) { const iconMap = { - elasticsearch: 'logoElasticSearch', + elasticsearch: 'logoElasticsearch', kibana: 'logoKibana', logstash: 'logoLogstash', beats: 'logoBeats', @@ -64,7 +64,7 @@ export function ClusterItemContainer(props) { - +

{ props.title } diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/index.js b/x-pack/plugins/monitoring/public/components/cluster/overview/index.js index cb76698555ad4b..747407bf650c73 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/index.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/index.js @@ -20,6 +20,7 @@ export function Overview(props) { ( + + Health: + + ); + return ( ); } diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/index.js b/x-pack/plugins/monitoring/public/components/elasticsearch/index.js index 3a2f35a8627a78..e09740e6b604ef 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/index.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/index.js @@ -5,3 +5,5 @@ */ export { ElasticsearchOverview } from './overview'; +export { ElasticsearchNodes } from './nodes'; +export { ElasticsearchIndices } from './indices'; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/index_detail_status/index.js b/x-pack/plugins/monitoring/public/components/elasticsearch/index_detail_status/index.js new file mode 100644 index 00000000000000..2eb378b298085e --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/index_detail_status/index.js @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment } from 'react'; +import { SummaryStatus } from '../../summary_status'; +import { ElasticsearchStatusIcon } from '../status_icon'; +import { formatMetric } from '../../../lib/format_number'; + +export function IndexDetailStatus({ stats }) { + const { + dataSize, + documents: documentCount, + totalShards, + unassignedShards, + status + } = stats; + + const metrics = [ + { + label: 'Total', + value: formatMetric(dataSize.total, '0.0 b'), + dataTestSubj: 'dataSize' + }, + { + label: 'Primaries', + value: formatMetric(dataSize.primaries, '0.0 b'), + dataTestSubj: 'dataSizePrimaries' + }, + { + label: 'Documents', + value: formatMetric(documentCount, '0.[0]a'), + dataTestSubj: 'documentCount' + }, + { + label: 'Total Shards', + value: formatMetric(totalShards, 'int_commas'), + dataTestSubj: 'totalShards' + }, + { + label: 'Unassigned Shards', + value: formatMetric(unassignedShards, 'int_commas'), + dataTestSubj: 'unassignedShards' + } + ]; + + const IconComponent = ({ status }) => ( + + Health: + + ); + + return ( + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/indices/index.js b/x-pack/plugins/monitoring/public/components/elasticsearch/indices/index.js new file mode 100644 index 00000000000000..a6a89822f6f04a --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/indices/index.js @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ElasticsearchIndices } from './indices'; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/indices/indices.js b/x-pack/plugins/monitoring/public/components/elasticsearch/indices/indices.js new file mode 100644 index 00000000000000..31cc551bb14382 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/indices/indices.js @@ -0,0 +1,117 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment } from 'react'; +import { capitalize, get } from 'lodash'; +import { SORT_ASCENDING, SORT_DESCENDING } from '../../../../common/constants'; +import { LARGE_FLOAT, LARGE_BYTES, LARGE_ABBREVIATED } from '../../../../common/formatting'; +import { formatMetric } from '../../../lib/format_number'; +import { ElasticsearchStatusIcon } from '../status_icon'; +import { ClusterStatus } from '../cluster_status'; +import { MonitoringTable } from '../../'; +import { EuiLink } from '@elastic/eui'; +import { KuiTableRowCell, KuiTableRow } from '@kbn/ui-framework/components'; +import { SytemIndicesCheckbox } from './system_indices_checkbox'; + +const filterFields = ['name', 'status']; +const columns = [ + { title: 'Name', sortKey: 'name', secondarySortOrder: SORT_ASCENDING }, + { title: 'Status', sortKey: 'status_sort', sortOrder: SORT_DESCENDING }, // default sort: red, then yellow, then green + { title: 'Document Count', sortKey: 'doc_count' }, + { title: 'Data', sortKey: 'data_size' }, + { title: 'Index Rate', sortKey: 'index_rate' }, + { title: 'Search Rate', sortKey: 'search_rate' }, + { title: 'Unassigned Shards', sortKey: 'unassigned_shards' } +]; +const IndexRow = ({ status, ...props }) => ( + + + + {props.name} + + + +
+   + {capitalize(status)} +
+
+ + {formatMetric(get(props, 'doc_count'), LARGE_ABBREVIATED)} + + + {formatMetric(get(props, 'data_size'), LARGE_BYTES)} + + + {formatMetric(get(props, 'index_rate'), LARGE_FLOAT, '/s')} + + + {formatMetric(get(props, 'search_rate'), LARGE_FLOAT, '/s')} + + + {formatMetric(get(props, 'unassigned_shards'), '0')} + +
+); + +const getNoDataMessage = filterText => { + if (filterText) { + return ( +
+

+ There are no indices that match your selection with the filter [{filterText.trim()}]. + Try changing the filter or the time range selection. +

+

+ If you are looking for system indices (e.g., .kibana), try checking ‘Show system indices’. +

+
+ ); + } + return ( +
+

There are no indices that match your selections. Try changing the time range selection.

+

If you are looking for system indices (e.g., .kibana), try checking ‘Show system indices’.

+
+ ); +}; + +const renderToolBarSection = ({ showSystemIndices, toggleShowSystemIndices, ...props }) => ( + +); + +export function ElasticsearchIndices({ clusterStatus, indices, ...props }) { + return ( + + + + + ); +} + diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/index_listing/show_system_indices_checkbox.js b/x-pack/plugins/monitoring/public/components/elasticsearch/indices/system_indices_checkbox.js similarity index 95% rename from x-pack/plugins/monitoring/public/components/elasticsearch/index_listing/show_system_indices_checkbox.js rename to x-pack/plugins/monitoring/public/components/elasticsearch/indices/system_indices_checkbox.js index 4f2ec1b5c5897e..bfda69ae856e74 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/index_listing/show_system_indices_checkbox.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/indices/system_indices_checkbox.js @@ -14,7 +14,7 @@ import { } from '@elastic/eui'; import { TABLE_ACTION_RESET_PAGING } from '../../../../common/constants'; -export class ShowSytemIndicesCheckbox extends React.Component { +export class SytemIndicesCheckbox extends React.Component { constructor(props) { super(props); this.state = { showSystemIndices: props.showSystemIndices }; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/node/index.js b/x-pack/plugins/monitoring/public/components/elasticsearch/node/index.js new file mode 100644 index 00000000000000..f8277a78f6f8ea --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/node/index.js @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { NodeStatusIcon } from './status_icon'; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/node/status_icon.js b/x-pack/plugins/monitoring/public/components/elasticsearch/node/status_icon.js index edd7db5f1f70fa..5a7ed469eba35c 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/node/status_icon.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/node/status_icon.js @@ -5,12 +5,12 @@ */ import React from 'react'; -import { StatusIcon } from 'plugins/monitoring/components/status_icon'; +import { StatusIcon } from '../../status_icon'; -export function NodeStatusIcon({ status }) { - const type = (status === 'Online') ? StatusIcon.TYPES.GREEN : StatusIcon.TYPES.GRAY; +export function NodeStatusIcon({ isOnline, status }) { + const type = isOnline ? StatusIcon.TYPES.GREEN : StatusIcon.TYPES.GRAY; return ( - + ); } diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/node_detail_status/index.js b/x-pack/plugins/monitoring/public/components/elasticsearch/node_detail_status/index.js new file mode 100644 index 00000000000000..b74ce8c5829775 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/node_detail_status/index.js @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment } from 'react'; +import { SummaryStatus } from '../../summary_status'; +import { NodeStatusIcon } from '../node'; +import { formatMetric } from '../../../lib/format_number'; + +export function NodeDetailStatus({ stats }) { + const { + transport_address: transportAddress, + usedHeap, + freeSpace, + documents, + dataSize, + indexCount, + totalShards, + nodeTypeLabel, + status, + isOnline, + } = stats; + + const metrics = [ + { + value: transportAddress, + dataTestSubj: 'transportAddress' + }, + { + label: 'JVM Heap', + value: formatMetric(usedHeap, '0,0.[00]', '%', { prependSpace: false }), + dataTestSubj: 'jvmHeap' + }, + { + label: 'Free Disk Space', + value: formatMetric(freeSpace, '0.0 b'), + dataTestSubj: 'freeDiskSpace' + }, + { + label: 'Documents', + value: formatMetric(documents, '0.[0]a'), + dataTestSubj: 'documentCount' + }, + { + label: 'Data', + value: formatMetric(dataSize, '0.0 b'), + dataTestSubj: 'dataSize' + }, + { + label: 'Indices', + value: formatMetric(indexCount, 'int_commas'), + dataTestSubj: 'indicesCount' + }, + { + label: 'Shards', + value: formatMetric(totalShards, 'int_commas'), + dataTestSubj: 'shardsCount' + }, + { + label: 'Type', + value: nodeTypeLabel, + dataTestSubj: 'nodeType' + } + ]; + + const IconComponent = ({ status, isOnline }) => ( + + Status: + + ); + + return ( + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/node_listing/__tests__/__snapshots__/cells.test.js.snap b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/__snapshots__/cells.test.js.snap similarity index 100% rename from x-pack/plugins/monitoring/public/components/elasticsearch/node_listing/__tests__/__snapshots__/cells.test.js.snap rename to x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/__snapshots__/cells.test.js.snap diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/node_listing/__tests__/cells.test.js b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/cells.test.js similarity index 100% rename from x-pack/plugins/monitoring/public/components/elasticsearch/node_listing/__tests__/cells.test.js rename to x-pack/plugins/monitoring/public/components/elasticsearch/nodes/__tests__/cells.test.js diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/node_listing/cells.js b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/cells.js similarity index 100% rename from x-pack/plugins/monitoring/public/components/elasticsearch/node_listing/cells.js rename to x-pack/plugins/monitoring/public/components/elasticsearch/nodes/cells.js diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/index.js b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/index.js new file mode 100644 index 00000000000000..3f9d9e3bf0b1be --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/index.js @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ElasticsearchNodes } from './nodes'; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js new file mode 100644 index 00000000000000..e64e385b0687e8 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js @@ -0,0 +1,171 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment } from 'react'; +import { get } from 'lodash'; +import { SORT_ASCENDING } from '../../../../common/constants'; +import { NodeStatusIcon } from '../node'; +import { extractIp } from '../../../lib/extract_ip'; // TODO this is only used for elasticsearch nodes summary / node detail, so it should be moved to components/elasticsearch/nodes/lib +import { ClusterStatus } from '../cluster_status'; +import { MonitoringTable } from '../../'; +import { MetricCell, OfflineCell } from './cells'; +import { EuiLink, EuiToolTip } from '@elastic/eui'; +import { KuiTableRowCell, KuiTableRow } from '@kbn/ui-framework/components'; + +const filterFields = ['node.name', 'status', 'type', 'transport_address']; +const getColumns = showCgroupMetricsElasticsearch => { + const cols = []; + cols.push({ title: 'Name', sortKey: 'node.name', sortOrder: SORT_ASCENDING }); + cols.push({ title: 'Status', sortKey: 'online' }); + if (showCgroupMetricsElasticsearch) { + cols.push({ title: 'CPU Usage', sortKey: 'node_cgroup_quota.lastVal' }); + cols.push({ + title: 'CPU Throttling', + sortKey: 'node_cgroup_throttled.lastVal' + }); + } else { + cols.push({ title: 'CPU Usage', sortKey: 'node_cpu_utilization.lastVal' }); + cols.push({ title: 'Load Average', sortKey: 'node_load_average.lastVal' }); + } + cols.push({ title: 'JVM Memory', sortKey: 'node_jvm_mem_percent.lastVal' }); + cols.push({ title: 'Disk Free Space', sortKey: 'node_free_space.lastVal' }); + cols.push({ title: 'Shards', sortKey: 'shardCount' }); + return cols; +}; + +const nodeRowFactory = showCgroupMetricsElasticsearch => { + return class NodeRow extends React.Component { + constructor(props) { + super(props); + } + + isOnline() { + return this.props.isOnline === true; + } + + getCpuComponents() { + const isOnline = this.isOnline(); + if (showCgroupMetricsElasticsearch) { + return [ + , + + ]; + } + return [ + , + + ]; + } + + getShardCount() { + if (this.isOnline()) { + return ( + +
+ {get(this.props, 'shardCount')} +
+
+ ); + } + return ; + } + + render() { + const isOnline = this.isOnline(); + const status = this.props.isOnline ? 'Online' : 'Offline'; + + return ( + + +
+ + + +   + + {this.props.name} + +
+
+ {extractIp(this.props.transport_address)} +
+
+ +
+ {' '} + {status} +
+
+ {this.getCpuComponents()} + + + {this.getShardCount()} +
+ ); + } + }; +}; + +export function ElasticsearchNodes({ clusterStatus, nodes, showCgroupMetricsElasticsearch, ...props }) { + const columns = getColumns(showCgroupMetricsElasticsearch); + + return ( + + + + + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/status_icon.js b/x-pack/plugins/monitoring/public/components/elasticsearch/status_icon.js index 3374553188f178..623fbbfde30a68 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/status_icon.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/status_icon.js @@ -5,7 +5,7 @@ */ import React from 'react'; -import { StatusIcon } from 'plugins/monitoring/components/status_icon'; +import { StatusIcon } from '../status_icon'; export function ElasticsearchStatusIcon({ status }) { const type = (() => { diff --git a/x-pack/plugins/monitoring/public/components/index.js b/x-pack/plugins/monitoring/public/components/index.js index fe11e0b827861a..665ef7b5fce9db 100644 --- a/x-pack/plugins/monitoring/public/components/index.js +++ b/x-pack/plugins/monitoring/public/components/index.js @@ -5,9 +5,15 @@ */ export { MonitoringTimeseriesContainer } from './chart'; +export { MonitoringTable } from './table'; +export { Tooltip } from './tooltip'; export { NoData } from './no_data'; export { License } from './license'; export { StatusIcon } from './status_icon'; -export { SummaryStatus } from './summary_status'; +export { SummaryStatus } from './summary_status'; // TODO this line can be removed, component is only used by other components export { PageLoading } from './page_loading'; -export { ElasticsearchOverview } from './elasticsearch'; +export { + ElasticsearchOverview, + ElasticsearchNodes, + ElasticsearchIndices +} from './elasticsearch'; diff --git a/x-pack/plugins/monitoring/public/components/kibana/cluster_status/index.js b/x-pack/plugins/monitoring/public/components/kibana/cluster_status/index.js new file mode 100644 index 00000000000000..f8fdb6efcb1e4b --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/kibana/cluster_status/index.js @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment } from 'react'; +import { SummaryStatus } from '../../summary_status'; +import { KibanaStatusIcon } from '../status_icon'; +import { formatMetric } from '../../../lib/format_number'; + +export function ClusterStatus({ stats }) { + const { + concurrent_connections: connections, + count: instances, + memory_limit: memLimit, + memory_size: memSize, + requests_total: requests, + response_time_max: maxResponseTime, + status, + } = stats; + + const metrics = [ + { + label: 'Instances', + value: instances, + dataTestSubj: 'instances' + }, + { + label: 'Memory', + value: formatMetric(memSize, 'byte') + ' / ' + formatMetric(memLimit, 'byte'), + dataTestSubj: 'memory' + }, + { + label: 'Requests', + value: requests, + dataTestSubj: 'requests' + }, + { + label: 'Connections', + value: connections, + dataTestSubj: 'connections' + }, + { + label: 'Max. Response Time', + value: formatMetric(maxResponseTime, '0', 'ms'), + dataTestSubj: 'maxResponseTime' + } + ]; + + const IconComponent = ({ status }) => ( + + Status: + + ); + + return ( + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/kibana/detail_status/index.js b/x-pack/plugins/monitoring/public/components/kibana/detail_status/index.js new file mode 100644 index 00000000000000..b89019746a61b0 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/kibana/detail_status/index.js @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment } from 'react'; +import { SummaryStatus } from '../../summary_status'; +import { KibanaStatusIcon } from '../status_icon'; +import { formatMetric } from '../../../lib/format_number'; + +export function DetailStatus({ stats }) { + const { + transport_address: transportAddress, + os_memory_free: osFreeMemory, + version, + uptime, + status + } = stats; + + const metrics = [ + { + value: transportAddress, + dataTestSubj: 'transportAddress' + }, + { + label: 'OS Free Memory', + value: formatMetric(osFreeMemory, 'byte'), + dataTestSubj: 'osFreeMemory' + }, + { + label: 'Version', + value: version, + dataTestSubj: 'version' + }, + { + label: 'Uptime', + value: formatMetric(uptime, 'time_since'), + dataTestSubj: 'uptime' + } + ]; + + const IconComponent = ({ status }) => ( + + Status: + + ); + + return ( + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/logstash/cluster_status/index.js b/x-pack/plugins/monitoring/public/components/logstash/cluster_status/index.js new file mode 100644 index 00000000000000..923cd9e17d93e0 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/cluster_status/index.js @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { SummaryStatus } from '../../summary_status'; +import { formatMetric } from '../../../lib/format_number'; + +export function ClusterStatus({ stats }) { + const { + node_count: nodeCount, + avg_memory_used: avgMemoryUsed, + avg_memory: avgMemory, + events_in_total: eventsInTotal, + events_out_total: eventsOutTotal + } = stats; + + const metrics = [ + { + label: 'Nodes', + value: nodeCount, + dataTestSubj: 'node_count' + }, + { + label: 'Memory', + value: formatMetric(avgMemoryUsed, 'byte') + ' / ' + formatMetric(avgMemory, 'byte'), + dataTestSubj: 'memory_used' + }, + { + label: 'Events Received', + value: formatMetric(eventsInTotal, '0.[0]a'), + dataTestSubj: 'events_in_total' + }, + { + label: 'Events Emitted', + value: formatMetric(eventsOutTotal, '0.[0]a'), + dataTestSubj: 'events_out_total' + } + ]; + + return ( + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/logstash/detail_status/index.js b/x-pack/plugins/monitoring/public/components/logstash/detail_status/index.js new file mode 100644 index 00000000000000..a441396f406565 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/detail_status/index.js @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { SummaryStatus } from '../../summary_status'; +import { formatMetric } from '../../../lib/format_number'; + +export function DetailStatus({ stats }) { + const { + http_address: httpAddress, + events, + reloads, + pipeline, + queue_type: queueType, + version, + uptime + } = stats; + + const firstMetrics = [ + { + value: httpAddress, + dataTestSubj: 'httpAddress' + }, + { + label: 'Events Received', + value: formatMetric(events.in, '0.[0]a'), + dataTestSubj: 'eventsIn' + }, + { + label: 'Events Emitted', + value: formatMetric(events.out, '0.[0]a'), + dataTestSubj: 'eventsOut' + }, + { + label: 'Config Reloads', + value: reloads.successes, + dataTestSubj: 'numReloads' + }, + { + label: 'Pipeline Workers', + value: pipeline.workers, + dataTestSubj: 'pipelineWorkers' + }, + { + label: 'Batch Size', + value: pipeline.batch_size, + dataTestSubj: 'pipelineBatchSize' + } + ]; + + const lastMetrics = [ + { + label: 'Version', + value: version, + dataTestSubj: 'version' + }, + { + label: 'Uptime', + value: formatMetric(uptime, 'time_since'), + dataTestSubj: 'uptime' + } + ]; + + // make queueType conditional + const metrics = [...firstMetrics]; + if (queueType) { + metrics.push({ + label: 'Queue Type', + value: queueType, + dataTestSubj: 'queueType' + }); + } + metrics.push(...lastMetrics); + + return ( + + ); +} diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/__tests__/index.test.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/__tests__/index.test.js index bc924d6881b0e5..5e54be90afce04 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/__tests__/index.test.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/__tests__/index.test.js @@ -62,7 +62,7 @@ describe('PipelineViewer component', () => { ] }); - timeseriesTooltipXValueFormatter = {}; + timeseriesTooltipXValueFormatter = () => {}; pipelineState = { config: { graph diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js index daa7b61fa92d15..a521650bfb1688 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/__tests__/plugin_vertex.js @@ -40,11 +40,17 @@ describe('PluginVertex', () => { [ 1516667386000, 0.3 ] ] }, - events_per_millisecond: { + events_in_per_millisecond: { data: [ [ 1516667383000, 0.01 ], [ 1516667386000, 0.02 ] ] + }, + events_out_per_millisecond: { + data: [ + [ 1516667383000, 0.01 ], + [ 1516667386000, 0.03 ] + ] } } }; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/if_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/if_vertex.js index 755efc2d34ae7a..39d76ae6f882c6 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/if_vertex.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/if_vertex.js @@ -40,18 +40,34 @@ export class IfVertex extends Vertex { return this.outgoingEdges.find(e => e.when === true); } + get trueEdges() { + return this.outgoingEdges.filter(e => e.when === true); + } + get falseEdge() { return this.outgoingEdges.find(e => e.when === false); } + get falseEdges() { + return this.outgoingEdges.filter(e => e.when === false); + } + get trueOutgoingVertex() { return this.trueEdge ? this.trueEdge.to : null; } + get trueOutgoingVertices() { + return this.trueEdges.map(e => e.to); + } + get falseOutgoingVertex() { return this.falseEdge ? this.falseEdge.to : null; } + get falseOutgoingVertices() { + return this.falseEdges.map(e => e.to); + } + get next() { const trueDescendants = this.trueOutgoingVertex ? this.trueOutgoingVertex.descendants().vertices : []; const falseDescendants = this.falseOutgoingVertex ? this.falseOutgoingVertex.descendants().vertices : []; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js index 08b6c15f439a44..1e8a79d7199920 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/graph/plugin_vertex.js @@ -57,7 +57,9 @@ export class PluginVertex extends Vertex { } get eventsPerSecond() { - const eventsPerMillisecond = this.stats.events_per_millisecond; + const eventsPerMillisecond = this.isInput + ? this.stats.events_out_per_millisecond + : this.stats.events_in_per_millisecond; return { ...omit(eventsPerMillisecond, 'data'), data: get(eventsPerMillisecond, 'data', []).map(([x, y]) => [x, y * 1000]) diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/element.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/element.js new file mode 100644 index 00000000000000..36cf2714cfd6e4 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/element.js @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export class Element { + constructor(id, statement, depth, parentId) { + this.id = id; + this.statement = statement; + this.depth = depth; + this.parentId = parentId; + } +} diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/else_element.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/else_element.js new file mode 100644 index 00000000000000..f8b40ee790cab6 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/else_element.js @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Element } from './element'; + +export class ElseElement extends Element { + constructor(statement, depth, parentId) { + const { id } = statement; + super(`${id}_else`, statement, depth, parentId); + } +} diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/else_element.test.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/else_element.test.js new file mode 100644 index 00000000000000..d00309da118a44 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/else_element.test.js @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ElseElement } from './else_element'; + +describe('ElseElement', () => { + let statement; + let depth; + let parentId; + + beforeEach(() => { + statement = { + id: 'statement_id' + }; + + depth = 2; + parentId = 'parent_id'; + }); + + it('has expected props', () => { + const element = new ElseElement(statement, depth, parentId); + + expect(element.id).toBe('statement_id_else'); + expect(element.statement).toBe(statement); + expect(element.depth).toBe(depth); + expect(element.parentId).toBe(parentId); + }); +}); diff --git a/x-pack/dev-tools/functional_tests/lib/get_ftr_config.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/flatten_pipeline_section.js similarity index 52% rename from x-pack/dev-tools/functional_tests/lib/get_ftr_config.js rename to x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/flatten_pipeline_section.js index 65a584123d86eb..fa158ffd75d386 100644 --- a/x-pack/dev-tools/functional_tests/lib/get_ftr_config.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/flatten_pipeline_section.js @@ -4,11 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { readFtrConfigFile } from '@kbn/plugin-helpers'; +export function flattenPipelineSection(pipelineSection, depth = 0, parentId = null) { + const list = []; -import { FTR_CONFIG_PATH } from './paths'; -import { log } from './log'; + pipelineSection.forEach(statement => { + list.push(...statement.toList(depth, parentId)); + }); -export async function getFtrConfig() { - return await readFtrConfigFile(log, FTR_CONFIG_PATH); + return list; } diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/flatten_pipeline_section.test.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/flatten_pipeline_section.test.js new file mode 100644 index 00000000000000..7097175a68a413 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/flatten_pipeline_section.test.js @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { flattenPipelineSection } from './flatten_pipeline_section'; +import { PluginStatement } from '../pipeline/plugin_statement'; +import { IfStatement } from '../pipeline/if_statement'; + +describe('flattenPipelineSection', () => { + let pipelineSection; + + beforeEach(() => { + pipelineSection = []; + }); + + it('creates list for only-plugin pipeline section', () => { + pipelineSection = [ + PluginStatement.fromPipelineGraphVertex({ id: 'first' }), + PluginStatement.fromPipelineGraphVertex({ id: 'second' }) + ]; + + const result = flattenPipelineSection(pipelineSection, 0, null); + + expect(result).toHaveLength(2); + expect(result[0].parentId).toBe(null); + expect(result[0].depth).toBe(0); + expect(result[0].id).toBe('first'); + expect(result[1].parentId).toBe(null); + expect(result[1].depth).toBe(0); + expect(result[1].id).toBe('second'); + }); + + it('flattens pipeline with if statement', () => { + pipelineSection = [ + PluginStatement.fromPipelineGraphVertex({ id: 'first' }), + new IfStatement( + { id: 'if_parent' }, + [ PluginStatement.fromPipelineGraphVertex({ id: 'if_child1' })], + [] + ) + ]; + + const result = flattenPipelineSection(pipelineSection, 0, null); + + expect(result).toHaveLength(3); + expect(result[0].id).toBe('first'); + expect(result[1].id).toBe('if_parent'); + expect(result[1].parentId).toBe(null); + expect(result[1].depth).toBe(0); + expect(result[2].id).toBe('if_child1'); + expect(result[2].parentId).toBe('if_parent'); + expect(result[2].depth).toBe(1); + }); + + it('flattens pipeline with else statement', () => { + pipelineSection = [ + new IfStatement( + { id: 'if_parent' }, + [ PluginStatement.fromPipelineGraphVertex({ id: 'if_child1' })], + [ PluginStatement.fromPipelineGraphVertex({ id: 'else_child1' })] + ) + ]; + + const result = flattenPipelineSection(pipelineSection, 0, null); + + expect(result).toHaveLength(4); + expect(result[0].id).toBe('if_parent'); + + expect(result[1].id).toBe('if_child1'); + expect(result[1].parentId).toBe('if_parent'); + expect(result[1].depth).toBe(1); + + expect(result[2].constructor.name).toBe('ElseElement'); + expect(result[2].depth).toBe(0); + expect(result[2].parentId).toBe(null); + + expect(result[3].id).toBe('else_child1'); + expect(result[3].parentId).toBe('if_parent_else'); + expect(result[3].depth).toBe(1); + }); + + it('flattens pipeline section with if/else and nested if', () => { + pipelineSection = [ + new IfStatement( + { id: 'if_parent' }, + [ PluginStatement.fromPipelineGraphVertex({ id: 'if_child1' })], + [ + new IfStatement( + { id: 'if_parent2' }, + [ PluginStatement.fromPipelineGraphVertex({ id: 'if_child2' })], + [] + ), + PluginStatement.fromPipelineGraphVertex({ id: 'else_child1' })] + ) + ]; + + const result = flattenPipelineSection(pipelineSection, 0, null); + + expect(result).toHaveLength(6); + expect(result[1].id).toBe('if_child1'); + expect(result[1].depth).toBe(1); + expect(result[1].parentId).toBe('if_parent'); + + expect(result[2].id).toBe('if_parent_else'); + expect(result[2].depth).toBe(0); + expect(result[2].parentId).toBe(null); + + expect(result[3].id).toBe('if_parent2'); + expect(result[3].depth).toBe(1); + expect(result[3].parentId).toBe('if_parent_else'); + + expect(result[4].id).toBe('if_child2'); + expect(result[4].depth).toBe(2); + expect(result[4].parentId).toBe('if_parent2'); + + expect(result[5].id).toBe('else_child1'); + expect(result[5].depth).toBe(1); + expect(result[5].parentId).toBe('if_parent_else'); + }); +}); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/if_element.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/if_element.js new file mode 100644 index 00000000000000..9b9b78d451e5a7 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/if_element.js @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Element } from './element'; + +export class IfElement extends Element { + constructor(statement, depth, parentId) { + const { id } = statement; + super(id, statement, depth, parentId); + } +} diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/if_element.test.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/if_element.test.js new file mode 100644 index 00000000000000..0874bca6d3e97c --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/if_element.test.js @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IfElement } from './if_element'; + +describe('IfElement', () => { + let statement; + let depth; + let parentId; + + beforeEach(() => { + statement = { + id: 'statement_id' + }; + + depth = 1; + parentId = 'parent_id'; + }); + + it('has expected props', () => { + const element = new IfElement(statement, depth, parentId); + + expect(element.id).toBe('statement_id'); + expect(element.statement).toBe(statement); + expect(element.depth).toBe(1); + expect(element.parentId).toBe('parent_id'); + }); +}); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/index.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/index.js new file mode 100644 index 00000000000000..02a013c3fc04d0 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/index.js @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { List } from './list'; diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/list.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/list.js new file mode 100644 index 00000000000000..830ea9e67ffceb --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/list.js @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { flattenPipelineSection } from './flatten_pipeline_section'; + +export class List { + constructor(inputs, filters, outputs, queue) { + this.inputs = inputs; + this.filters = filters; + this.outputs = outputs; + this.queue = queue; + } + + static fromPipeline(pipeline) { + const { + inputStatements, + filterStatements, + outputStatements, + queue + } = pipeline; + + return new List( + flattenPipelineSection(inputStatements), + flattenPipelineSection(filterStatements), + flattenPipelineSection(outputStatements), + queue, + ); + } +} diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/list.test.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/list.test.js new file mode 100644 index 00000000000000..3b7c85540ed518 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/list.test.js @@ -0,0 +1,147 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { List } from './list'; +import { PluginStatement } from '../pipeline/plugin_statement'; +import { IfStatement } from '../pipeline/if_statement'; +import { PluginElement } from './plugin_element'; +import { IfElement } from './if_element'; +import { ElseElement } from './else_element'; + +describe('pipelineToList', () => { + let pipeline; + + beforeEach(() => { + pipeline = { + inputStatements: [ + PluginStatement.fromPipelineGraphVertex({ id: 'first' }), + ], + filterStatements: [ + new IfStatement( + { id: 'if' }, + [ PluginStatement.fromPipelineGraphVertex({ id: 'if_child' })], + [ PluginStatement.fromPipelineGraphVertex({ id: 'else_child' })] + ) + ], + outputStatements: [ + PluginStatement.fromPipelineGraphVertex({ id: 'output' }) + ], + queue: { } + }; + }); + + it('creates list with element for each statement', () => { + const result = List.fromPipeline(pipeline); + const { + inputs, + filters, + outputs + } = result; + + expect(inputs).toHaveLength(1); + expect(filters).toHaveLength(4); + expect(outputs).toHaveLength(1); + }); + + it('creates list with if in outputs', () => { + pipeline.outputStatements.push( + new IfStatement( + { id: 'output_if' }, + [ PluginStatement.fromPipelineGraphVertex({ id: 'output_true' })], + [ PluginStatement.fromPipelineGraphVertex({ id: 'output_else' })] + ) + ); + + const result = List.fromPipeline(pipeline); + const { + inputs, + filters, + outputs + } = result; + + expect(inputs).toHaveLength(1); + expect(filters).toHaveLength(4); + expect(outputs).toHaveLength(5); + expect(outputs[0]).toBeInstanceOf(PluginElement); + expect(outputs[1]).toBeInstanceOf(IfElement); + expect(outputs[2]).toBeInstanceOf(PluginElement); + expect(outputs[3]).toBeInstanceOf(ElseElement); + expect(outputs[4]).toBeInstanceOf(PluginElement); + }); + + it('creates list for multi-nested if/else statements in filter section', () => { + pipeline.filterStatements = [ + new IfStatement( + { id: 'filter_if_1' }, + [ + new IfStatement( + { id: 'filter_if_2' }, + [ PluginStatement.fromPipelineGraphVertex({ id: 'plugin_1' })], + [ ] + ) + ], + [ + new IfStatement( + { id: 'filter_if_3' }, + [ PluginStatement.fromPipelineGraphVertex({ id: 'plugin_2' })], + [ PluginStatement.fromPipelineGraphVertex({ id: 'plugin_3' })] + ) + ] + ) + ]; + + const result = List.fromPipeline(pipeline); + const { + inputs, + filters, + outputs + } = result; + + expect(inputs).toHaveLength(1); + expect(outputs).toHaveLength(1); + expect(filters).toHaveLength(8); + + expect(filters[0].id).toBe('filter_if_1'); + expect(filters[0].depth).toBe(0); + expect(filters[0].parentId).toBe(null); + expect(filters[0]).toBeInstanceOf(IfElement); + + expect(filters[1].id).toBe('filter_if_2'); + expect(filters[1].depth).toBe(1); + expect(filters[1].parentId).toBe('filter_if_1'); + expect(filters[1]).toBeInstanceOf(IfElement); + + expect(filters[2].id).toBe('plugin_1'); + expect(filters[2].depth).toBe(2); + expect(filters[2].parentId).toBe('filter_if_2'); + expect(filters[2]).toBeInstanceOf(PluginElement); + + expect(filters[3].id).toBe('filter_if_1_else'); + expect(filters[3].depth).toBe(0); + expect(filters[3].parentId).toBe(null); + expect(filters[3]).toBeInstanceOf(ElseElement); + + expect(filters[4].id).toBe('filter_if_3'); + expect(filters[4].depth).toBe(1); + expect(filters[4].parentId).toBe('filter_if_1_else'); + expect(filters[4]).toBeInstanceOf(IfElement); + + expect(filters[5].id).toBe('plugin_2'); + expect(filters[5].depth).toBe(2); + expect(filters[5].parentId).toBe('filter_if_3'); + expect(filters[5]).toBeInstanceOf(PluginElement); + + expect(filters[6].id).toBe('filter_if_3_else'); + expect(filters[6].depth).toBe(1); + expect(filters[6].parentId).toBe('filter_if_1_else'); + expect(filters[6]).toBeInstanceOf(ElseElement); + + expect(filters[7].id).toBe('plugin_3'); + expect(filters[7].depth).toBe(2); + expect(filters[7].parentId).toBe('filter_if_3_else'); + expect(filters[7]).toBeInstanceOf(PluginElement); + }); +}); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/plugin_element.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/plugin_element.js new file mode 100644 index 00000000000000..0a3601ffbcf8b4 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/plugin_element.js @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Element } from './element'; + +export class PluginElement extends Element { + constructor(statement, depth, parentId) { + const { id } = statement; + super(id, statement, depth, parentId); + } +} diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/plugin_element.test.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/plugin_element.test.js new file mode 100644 index 00000000000000..613b1a83dfea34 --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/list/plugin_element.test.js @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PluginElement } from './plugin_element'; + +describe('PluginElement', () => { + let statement; + let depth; + let parentId; + + beforeEach(() => { + statement = { + id: 'statement_id' + }; + + depth = 1; + parentId = 'parent_id'; + }); + + it('has expected props', () => { + const element = new PluginElement(statement, depth, parentId); + + expect(element.id).toBe('statement_id'); + expect(element.statement).toBe(statement); + expect(element.depth).toBe(1); + expect(element.parentId).toBe('parent_id'); + }); +}); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js index 1060c165720a3c..a4347f508a7768 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/if_statement.js @@ -7,6 +7,8 @@ import expect from 'expect.js'; import { IfStatement } from '../if_statement'; import { PluginVertex } from '../../graph/plugin_vertex'; +import { IfElement } from '../../list/if_element'; +import { PluginElement } from '../../list/plugin_element'; describe('IfStatement class', () => { let ifVertex; @@ -49,6 +51,8 @@ describe('IfStatement class', () => { esVertex.pipelineStage = 'output'; ifVertex.trueOutgoingVertex = esVertex; + ifVertex.trueOutgoingVertices = [ esVertex ]; + ifVertex.falseOutgoingVertices = []; }); it('creates a IfStatement from vertex props', () => { @@ -63,6 +67,7 @@ describe('IfStatement class', () => { expect(ifStatement.trueStatements.length).to.be(1); expect(ifStatement.elseStatements).to.be.an(Array); expect(ifStatement.elseStatements.length).to.be(0); + expect(ifStatement.vertex).to.eql(ifVertex); }); }); @@ -88,6 +93,9 @@ describe('IfStatement class', () => { ifVertex.trueOutgoingVertex = esVertex; ifVertex.falseOutgoingVertex = terminalVertex; + + ifVertex.trueOutgoingVertices = [ esVertex ]; + ifVertex.falseOutgoingVertices = [ terminalVertex ]; }); it('creates a IfStatement from vertex props', () => { @@ -102,6 +110,7 @@ describe('IfStatement class', () => { expect(ifStatement.trueStatements.length).to.be(1); expect(ifStatement.elseStatements).to.be.an(Array); expect(ifStatement.elseStatements.length).to.be(1); + expect(ifStatement.vertex).to.eql(ifVertex); }); }); @@ -126,6 +135,8 @@ describe('IfStatement class', () => { esVertex.pipelineStage = 'output'; ifVertex.trueOutgoingVertex = esVertex; + ifVertex.trueOutgoingVertices = [ esVertex ]; + ifVertex.falseOutgoingVertices = []; }); it('creates a IfStatement from vertex props', () => { @@ -140,6 +151,7 @@ describe('IfStatement class', () => { expect(ifStatement.trueStatements.length).to.be(2); expect(ifStatement.elseStatements).to.be.an(Array); expect(ifStatement.elseStatements.length).to.be(0); + expect(ifStatement.vertex).to.eql(ifVertex); }); }); @@ -171,6 +183,9 @@ describe('IfStatement class', () => { ifVertex.trueOutgoingVertex = esVertex; ifVertex.falseOutgoingVertex = terminalVertex; + + ifVertex.trueOutgoingVertices = [ esVertex ]; + ifVertex.falseOutgoingVertices = [ terminalVertex ]; }); it('creates a IfStatement from vertex props', () => { @@ -185,6 +200,32 @@ describe('IfStatement class', () => { expect(ifStatement.trueStatements.length).to.be(1); expect(ifStatement.elseStatements).to.be.an(Array); expect(ifStatement.elseStatements.length).to.be(2); + expect(ifStatement.vertex).to.eql(ifVertex); + }); + }); + + describe('toList', () => { + beforeEach(() => { + const esVertex = new PluginVertex({ edgesByFrom: {} }, { id: 'es_output' }); + esVertex.pipelineStage = 'output'; + + ifVertex.trueOutgoingVertices = [esVertex]; + ifVertex.falseOutgoingVertices = []; + }); + + it('creates list and sub-list for nested statements', () => { + const ifStatement = IfStatement.fromPipelineGraphVertex(ifVertex, pipelineStage); + + const result = ifStatement.toList(0, 'output'); + + expect(result).to.be.an(Array); + expect(result.length).to.be(2); + expect(result[0]).to.be.an(IfElement); + expect(result[0].id).to.be('0aef421'); + expect(result[1]).to.be.an(PluginElement); + const plugin = result[1]; + expect(plugin).to.be.an(PluginElement); + expect(plugin.id).to.be('es_output'); }); }); }); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js index 87ce39802da6d0..61bd562ce2a5a7 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/pipeline.js @@ -1579,6 +1579,185 @@ describe('Pipeline class', () => { }); }); + describe('Pipeline with if having two nested output statements', () => { + beforeEach(() => { + graph = new Graph(); + graph.update({ + vertices: [ + { + id: "the_if", + explicit_id: false, + type: "if", + condition: "[is_rt] == \"RT\"", + stats: {} + }, + { + plugin_type: "output", + type: "plugin", + config_name: "stdout", + id: "plugin_1", + meta: { + source: { + line: 124, + protocol: "str", + id: "pipeline", + column: 5 + } + }, + explicit_id: false, + stats: null + }, + { + plugin_type: "output", + type: "plugin", + config_name: "elasticsearch", + id: "plugin_2", + meta: { + source: { + line: 117, + protocol: "str", + id: "pipeline", + column: 5 + } + }, + explicit_id: true, + stats: null + }, + ], + edges: [ + { + id: "35591f523dee3465d4c38f20232c56db453a9e4258af5885bf8c79f517690bc5", + from: "the_if", + to: "plugin_1", + type: "boolean", + when: true + }, + { + id: "591f523dee3465d4c38f20232c56db453a9e4258af5885bf8c79f517690bc535", + from: "the_if", + to: "plugin_2", + type: "boolean", + when: true + } + ] + }); + }); + + it('has two child statements', () => { + const pipeline = Pipeline.fromPipelineGraph(graph); + + expect(pipeline.outputStatements.length).to.be(1); + const { trueStatements } = pipeline.outputStatements[0]; + expect(trueStatements.length).to.be(2); + expect(trueStatements[0].id).to.be('plugin_1'); + expect(trueStatements[1].id).to.be('plugin_2'); + expect(pipeline.outputStatements[0].elseStatements.length).to.be(0); + }); + }); + + describe('Pipeline with if having two nested else statements', () => { + beforeEach(() => { + graph = new Graph(); + graph.update({ + vertices: [ + { + id: "the_if", + explicit_id: false, + type: "if", + condition: "[is_rt] == \"RT\"", + stats: {} + }, + { + plugin_type: "output", + type: "plugin", + config_name: "stdout", + id: "plugin_1", + meta: { + source: { + line: 124, + protocol: "str", + id: "pipeline", + column: 5 + } + }, + explicit_id: false, + stats: null + }, + { + plugin_type: "output", + type: "plugin", + config_name: "elasticsearch", + id: "plugin_2", + meta: { + source: { + line: 117, + protocol: "str", + id: "pipeline", + column: 5 + } + }, + explicit_id: true, + stats: null + }, + { + plugin_type: "output", + type: "plugin", + config_name: "stdout", + id: "plugin_3", + meta: { + source: { + line: 120, + protocol: "str", + id: "pipeline", + column: 5 + } + }, + explicit_id: false, + stats: null + }, + ], + edges: [ + { + id: "35591f523dee3465d4c38f20232c56db453a9e4258af5885bf8c79f517690bc5", + from: "the_if", + to: "plugin_1", + type: "boolean", + when: false + }, + { + id: "591f523dee3465d4c38f20232c56db453a9e4258af5885bf8c79f517690bc535", + from: "the_if", + to: "plugin_2", + type: "boolean", + when: false + }, + { + id: "637281923dee3465d4c38f20232c56db453a9e4258af5885bf8c79f517690bc5", + from: "the_if", + to: "plugin_3", + type: "boolean", + when: true + } + ] + }); + }); + + it('has two child else statements', () => { + const pipeline = Pipeline.fromPipelineGraph(graph); + + expect(pipeline.outputStatements.length).to.be(1); + const { + trueStatements, + elseStatements + } = pipeline.outputStatements[0]; + expect(trueStatements.length).to.be(1); + expect(trueStatements[0].id).to.be('plugin_3'); + expect(elseStatements.length).to.be(2); + expect(elseStatements[0].id).to.be('plugin_1'); + expect(elseStatements[1].id).to.be('plugin_2'); + }); + }); + describe('Pipeline with nested ifs', () => { beforeEach(() => { graph = new Graph(); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js index 773a6caff95d3d..eafde6839eda25 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/plugin_statement.js @@ -39,6 +39,17 @@ describe('PluginStatement class', () => { expect(pluginStatement.meta).to.be(meta); expect(pluginStatement.pluginType).to.be('output'); expect(pluginStatement.name).to.be('elasticsearch'); + expect(pluginStatement.vertex).to.eql(pluginVertex); + }); + }); + + describe('toList', () => { + it('creates a list with plugin statement in it', () => { + const pluginStatement = PluginStatement.fromPipelineGraphVertex(pluginVertex); + + const result = pluginStatement.toList(); + expect(result.length).to.be(1); + expect(result[0].id).to.be('es_output'); }); }); }); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js index 91e954276c0d98..4f70604614864a 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/queue.js @@ -37,6 +37,7 @@ describe('Queue class', () => { expect(queue.stats).to.eql({}); expect(queue.meta).to.be(meta); expect(queue).to.be.a(Queue); + expect(queue.vertex).to.eql(queueVertex); }); }); -}); \ No newline at end of file +}); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js index ec74d8f72db995..f695bf36d2a155 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/__tests__/statement.js @@ -8,6 +8,7 @@ import expect from 'expect.js'; import { Statement } from '../statement'; describe('Statement class', () => { + let vertex; let meta; beforeEach(() => { @@ -18,21 +19,25 @@ describe('Statement class', () => { password: 'password' } }; + vertex = { + meta, + id: 'statement_id', + hasExplicitId: true, + stats: { } + }; }); describe('Statement from constructor', () => { it('creates a new Statement instance', () => { const statement = new Statement( - 'statement_id', - true, - {}, - meta + vertex ); expect(statement.id).to.be('statement_id'); expect(statement.hasExplicitId).to.be(true); expect(statement.stats).to.eql({}); expect(statement.meta).to.equal(meta); + expect(statement.vertex).to.eql(vertex); }); }); }); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/if_statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/if_statement.js index bc428975c2bdfa..84c43537a11e7e 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/if_statement.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/if_statement.js @@ -7,42 +7,70 @@ import { Statement } from './statement'; import { makeStatement } from './make_statement'; import { isVertexPipelineStage } from './utils'; +import { IfElement } from '../list/if_element'; +import { ElseElement } from '../list/else_element'; + +function makeStatementsForOutgoingVertices(outgoingVertices, statements, next, pipelineStage) { + outgoingVertices.forEach(vertex => { + let currentVertex = vertex; + while(isVertexPipelineStage(currentVertex, pipelineStage) && (currentVertex !== next)) { + statements.push(makeStatement(currentVertex, pipelineStage)); + currentVertex = currentVertex.next; + } + }); +} + +function addStatementsToList(list, statements, depth, id) { + statements.forEach(statement => { + list.push(...statement.toList(depth, id)); + }); +} export class IfStatement extends Statement { - constructor(id, hasExplicitId, stats, meta, condition, trueStatements, elseStatements) { - super(id, hasExplicitId, stats, meta); + constructor(vertex, trueStatements, elseStatements) { + super(vertex); + + const { name } = vertex; - this.condition = condition; + this.condition = name; this.trueStatements = trueStatements; this.elseStatements = elseStatements; } + toList(depth, parentId) { + const list = []; + + const ifElement = new IfElement(this, depth, parentId); + list.push(ifElement); + + const nestedElementDepth = depth + 1; + addStatementsToList(list, this.trueStatements, nestedElementDepth, ifElement.id); + + if (this.elseStatements.length) { + const elseElement = new ElseElement(this, depth, parentId); + list.push(elseElement); + + addStatementsToList(list, this.elseStatements, nestedElementDepth, elseElement.id); + } + + return list; + } + static fromPipelineGraphVertex(ifVertex, pipelineStage) { const trueStatements = []; const elseStatements = []; + const { + trueOutgoingVertices, + falseOutgoingVertices + } = ifVertex; - const trueVertex = ifVertex.trueOutgoingVertex; - const falseVertex = ifVertex.falseOutgoingVertex; const next = ifVertex.next; - let currentVertex = trueVertex; - while (isVertexPipelineStage(currentVertex, pipelineStage) && (currentVertex !== next)) { - trueStatements.push(makeStatement(currentVertex, pipelineStage)); - currentVertex = currentVertex.next; - } - - currentVertex = falseVertex; - while (currentVertex && isVertexPipelineStage(currentVertex, pipelineStage) && (currentVertex !== next)) { - elseStatements.push(makeStatement(currentVertex, pipelineStage)); - currentVertex = currentVertex.next; - } + makeStatementsForOutgoingVertices(trueOutgoingVertices, trueStatements, next, pipelineStage); + makeStatementsForOutgoingVertices(falseOutgoingVertices, elseStatements, next, pipelineStage); return new IfStatement( - ifVertex.id, - ifVertex.hasExplicitId, - ifVertex.stats, - ifVertex.meta, - ifVertex.name, + ifVertex, trueStatements, elseStatements ); diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/plugin_statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/plugin_statement.js index b1774c4ede7f7b..3ffc9d12017477 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/plugin_statement.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/plugin_statement.js @@ -5,22 +5,28 @@ */ import { Statement } from './statement'; +import { PluginElement } from '../list/plugin_element'; export class PluginStatement extends Statement { - constructor(id, hasExplicitId, stats, meta, pluginType, name) { - super(id, hasExplicitId, stats, meta); + constructor(vertex) { + super(vertex); + + const { + pluginType, + name + } = vertex; + this.pluginType = pluginType; // input, filter, or output this.name = name; // twitter, grok, elasticsearch, etc. } + toList(depth, parentId) { + return [ new PluginElement(this, depth, parentId) ]; + } + static fromPipelineGraphVertex(pluginVertex) { return new PluginStatement( - pluginVertex.id, - pluginVertex.hasExplicitId, - pluginVertex.stats, - pluginVertex.meta, - pluginVertex.pluginType, - pluginVertex.name + pluginVertex ); } } diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/queue.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/queue.js index 9158d65cc06779..1a2a0b604918ba 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/queue.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/queue.js @@ -9,10 +9,7 @@ import { Statement } from './statement'; export class Queue extends Statement { static fromPipelineGraphVertex(queueVertex) { return new Queue( - queueVertex.id, - queueVertex.hasExplicitId, - queueVertex.stats, - queueVertex.meta + queueVertex ); } } diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/statement.js b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/statement.js index eda75bc3771f67..c273c3ea0d0d65 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/statement.js +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/models/pipeline/statement.js @@ -5,10 +5,21 @@ */ export class Statement { - constructor(id, hasExplicitId, stats, meta) { + constructor(vertex) { + const { + id, + hasExplicitId, + stats, + meta + } = vertex; + this.id = id; this.hasExplicitId = hasExplicitId; this.stats = stats; this.meta = meta; + + // storing a direct reference to the source vertex is convenient + // for interoperability with components that use the existing graph + this.vertex = vertex; } } diff --git a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/detail_drawer.test.js.snap b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/detail_drawer.test.js.snap index 814d8b6c2aca2a..a332f27d906290 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/detail_drawer.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/logstash/pipeline_viewer/views/__test__/__snapshots__/detail_drawer.test.js.snap @@ -9,6 +9,7 @@ exports[`DetailDrawer component If vertices shows basic info and no stats for if - +

- +

This is a conditional statement in your pipeline. @@ -75,6 +80,7 @@ exports[`DetailDrawer component Plugin vertices Plugin does not have explicit ID - +

- +

This @@ -127,7 +137,9 @@ exports[`DetailDrawer component Plugin vertices Plugin does not have explicit ID size="l" />

- + - +

- +

This plugin @@ -406,7 +423,9 @@ exports[`DetailDrawer component Plugin vertices Plugin has explicit ID shows bas .

- + - +

- +

This is an internal structure used by Logstash to buffer events between inputs and the rest of the pipeline.

@@ -696,6 +720,7 @@ exports[`DetailDrawer component shows vertex title 1`] = ` - +

- + `; diff --git a/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/no_data.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/no_data.test.js.snap index 4781aaa33aeed0..1567323a0153fe 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/no_data.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/no_data/__tests__/__snapshots__/no_data.test.js.snap @@ -136,7 +136,7 @@ exports[`NoData should show text next to the spinner while checking a setting 1` class="euiHorizontalRule euiHorizontalRule--half euiHorizontalRule--marginLarge" />
- +
@@ -47,7 +49,9 @@ exports[`ExplainCollectionEnabled should explain about xpack.monitoring.collecti className="euiHorizontalRule euiHorizontalRule--half euiHorizontalRule--marginLarge" /> - +
@@ -111,13 +115,14 @@ exports[`ExplainCollectionEnabled should explain about xpack.monitoring.collecti
- +
@@ -85,7 +87,9 @@ exports[`ExplainCollectionInterval collection interval setting updates should sh - +
@@ -105,7 +109,9 @@ exports[`ExplainCollectionInterval collection interval setting updates should sh className="euiHorizontalRule euiHorizontalRule--half euiHorizontalRule--marginLarge" /> - +
@@ -172,13 +178,14 @@ exports[`ExplainCollectionInterval collection interval setting updates should sh
- +
@@ -268,7 +277,9 @@ exports[`ExplainCollectionInterval should explain about xpack.monitoring.collect className="euiHorizontalRule euiHorizontalRule--half euiHorizontalRule--marginLarge" /> - +
@@ -335,13 +346,14 @@ exports[`ExplainCollectionInterval should explain about xpack.monitoring.collect
,
( - {label}: {value} + {label ? label + ': ' : null} + {value} ); -const StatusIndicator = ({ status }) => { +const DefaultIconComponent = ({ status }) => ( + + Status: {( + + )} + +); + +const StatusIndicator = ({ status, isOnline, IconComponent }) => { if (isEmpty(status)) { return null; } return (
- Health: {' '} + {' '} {capitalize(status)}
); }; -export function SummaryStatus({ children, status, ...props }) { +export function SummaryStatus({ metrics, status, isOnline, IconComponent = DefaultIconComponent, ...props }) { return (
- {children.map(wrapChild)} + {metrics.map(wrapChild)} - +
); } + +SummaryStatus.propTypes = { + metrics: PropTypes.array.isRequired +}; diff --git a/x-pack/plugins/monitoring/public/components/table/toolbar.js b/x-pack/plugins/monitoring/public/components/table/toolbar.js index acb1b5a9383067..ba4b2f325ee8a3 100644 --- a/x-pack/plugins/monitoring/public/components/table/toolbar.js +++ b/x-pack/plugins/monitoring/public/components/table/toolbar.js @@ -17,7 +17,7 @@ export function MonitoringTableToolBar(props) { const searchBox = props.showSearchBox ? ( -
-
Nodes: - {{ status.nodesCount }} -
-
Indices: - {{ status.indicesCount }} -
-
Memory: - {{ status.memUsed|formatNumber:'byte' }} / {{ status.memMax|formatNumber:'byte' }} -
-
Total Shards: - {{ status.totalShards }} -
-
Unassigned Shards: - {{ status.unassignedShards }} -
-
Documents: - {{ status.documentCount|formatNumber:'int_commas' }} -
-
Data: - {{ status.dataSize|formatNumber:'byte' }} -
-
- Health: - - {{ status.status|capitalize }} -
-
-
diff --git a/x-pack/plugins/monitoring/public/directives/elasticsearch/cluster_status/index.js b/x-pack/plugins/monitoring/public/directives/elasticsearch/cluster_status/index.js index 87cdda14e86e63..0be64b18406a84 100644 --- a/x-pack/plugins/monitoring/public/directives/elasticsearch/cluster_status/index.js +++ b/x-pack/plugins/monitoring/public/directives/elasticsearch/cluster_status/index.js @@ -4,16 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; +import { render } from 'react-dom'; import { uiModules } from 'ui/modules'; -import template from './index.html'; +import { ClusterStatus } from 'plugins/monitoring/components/elasticsearch/cluster_status'; const uiModule = uiModules.get('monitoring/directives', []); uiModule.directive('monitoringClusterStatusElasticsearch', () => { return { restrict: 'E', - template, scope: { status: '=' + }, + link(scope, $el) { + scope.$watch('status', status => { + render(, $el[0]); + }); } }; }); diff --git a/x-pack/plugins/monitoring/public/directives/elasticsearch/index_listing/index.js b/x-pack/plugins/monitoring/public/directives/elasticsearch/index_listing/index.js deleted file mode 100644 index b0ba34d6f075a5..00000000000000 --- a/x-pack/plugins/monitoring/public/directives/elasticsearch/index_listing/index.js +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { capitalize, get } from 'lodash'; -import React from 'react'; -import { render } from 'react-dom'; -import { SORT_ASCENDING, SORT_DESCENDING } from '../../../../common/constants'; -import { LARGE_FLOAT, LARGE_BYTES, LARGE_ABBREVIATED } from '../../../../common/formatting'; -import { uiModules } from 'ui/modules'; -import { - KuiTableRowCell, - KuiTableRow, -} from '@kbn/ui-framework/components'; -import { MonitoringTable } from 'plugins/monitoring/components/table'; -import { ShowSytemIndicesCheckbox } from 'plugins/monitoring/components/elasticsearch/index_listing'; -import { ElasticsearchStatusIcon } from 'plugins/monitoring/components/elasticsearch/status_icon'; -import { formatMetric } from '../../../lib/format_number'; -import { - EuiLink, -} from '@elastic/eui'; - -const filterFields = ['name', 'status']; -const cols = [ - { title: 'Name', sortKey: 'name', secondarySortOrder: SORT_ASCENDING }, - { title: 'Status', sortKey: 'statusSort', sortOrder: SORT_DESCENDING }, // default sort: red, then yellow, then green - { title: 'Document Count', sortKey: 'doc_count' }, - { title: 'Data', sortKey: 'data_size' }, - { title: 'Index Rate', sortKey: 'index_rate' }, - { title: 'Search Rate', sortKey: 'search_rate' }, - { title: 'Unassigned Shards', sortKey: 'unassigned_shards' } -]; -const indexRowFactory = (scope, kbnUrl) => { - return class IndexRow extends React.Component { // eslint-disable-line react/no-multi-comp - constructor(props) { - super(props); - this.changePath = this.changePath.bind(this); - } - changePath() { - scope.$evalAsync(() => { - kbnUrl.changePath(`/elasticsearch/indices/${this.props.name}`); - }); - } - render() { - const status = this.props.status; - - return ( - - - - {this.props.name} - - - -
-   - {capitalize(status)} -
-
- - {formatMetric(get(this.props, 'doc_count'), LARGE_ABBREVIATED)} - - - {formatMetric(get(this.props, 'data_size'), LARGE_BYTES)} - - - {formatMetric(get(this.props, 'index_rate'), LARGE_FLOAT, '/s')} - - - {formatMetric(get(this.props, 'search_rate'), LARGE_FLOAT, '/s')} - - - {formatMetric(get(this.props, 'unassigned_shards'), '0')} - -
- ); - } - }; -}; - -const getNoDataMessage = filterText => { - if (filterText) { - return ( -
-

- There are no indices that match your selection with the filter [{filterText.trim()}]. - Try changing the filter or the time range selection. -

-

- If you are looking for system indices (e.g., .kibana), try checking ‘Show system indices’. -

-
- ); - } - return ( -
-

There are no indices that match your selections. Try changing the time range selection.

-

If you are looking for system indices (e.g., .kibana), try checking ‘Show system indices’.

-
- ); -}; - -const uiModule = uiModules.get('monitoring/directives', []); -uiModule.directive('monitoringIndexListing', kbnUrl => { - return { - restrict: 'E', - scope: { - indices: '=', - pageIndex: '=', - filterText: '=', - sortKey: '=', - sortOrder: '=', - onNewState: '=', - showSystemIndices: '=', - toggleShowSystemIndices: '=' - }, - link(scope, $el) { - const toggleShowSystemIndices = isChecked => { - scope.$evalAsync(() => { - scope.toggleShowSystemIndices(isChecked); - }); - }; - const renderToolBarSection = props => ( - - ); - - scope.$watch('indices', (indices = []) => { - const instancesTable = ( - - ); - render(instancesTable, $el[0]); - }); - } - }; -}); diff --git a/x-pack/plugins/monitoring/public/directives/elasticsearch/index_summary/index.html b/x-pack/plugins/monitoring/public/directives/elasticsearch/index_summary/index.html deleted file mode 100644 index 3a3d4848fa18e9..00000000000000 --- a/x-pack/plugins/monitoring/public/directives/elasticsearch/index_summary/index.html +++ /dev/null @@ -1,32 +0,0 @@ -
-
-
- Total: - {{ summary.dataSize.total|formatMetric:'0.0 b' }} -
-
- Primaries: - {{ summary.dataSize.primaries|formatMetric:'0.0 b' }} -
-
- Documents: - {{ summary.documents|formatMetric:'0.[0]a' }} -
-
- Total Shards: - {{ summary.totalShards|formatMetric:'0,0' }} -
-
- Unassigned Shards: - {{ summary.unassignedShards|formatMetric:'0,0' }} -
-
- Health: - - {{ summary.status|capitalize }} -
-
-
diff --git a/x-pack/plugins/monitoring/public/directives/elasticsearch/index_summary/index.js b/x-pack/plugins/monitoring/public/directives/elasticsearch/index_summary/index.js index b292ee173b272d..e1fa222a0ee80d 100644 --- a/x-pack/plugins/monitoring/public/directives/elasticsearch/index_summary/index.js +++ b/x-pack/plugins/monitoring/public/directives/elasticsearch/index_summary/index.js @@ -4,15 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; +import { render } from 'react-dom'; import { uiModules } from 'ui/modules'; -import template from './index.html'; +import { IndexDetailStatus } from 'plugins/monitoring/components/elasticsearch/index_detail_status'; const uiModule = uiModules.get('monitoring/directives', []); uiModule.directive('monitoringIndexSummary', () => { return { restrict: 'E', - template: template, - scope: { summary: '=' } + scope: { summary: '=' }, + link(scope, $el) { + scope.$watch('summary', summary => { + render(, $el[0]); + }); + } }; }); diff --git a/x-pack/plugins/monitoring/public/directives/elasticsearch/node_listing/index.js b/x-pack/plugins/monitoring/public/directives/elasticsearch/node_listing/index.js deleted file mode 100644 index de3a9efa505280..00000000000000 --- a/x-pack/plugins/monitoring/public/directives/elasticsearch/node_listing/index.js +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { get } from 'lodash'; -import React from 'react'; -import { render } from 'react-dom'; -import { uiModules } from 'ui/modules'; -import { - KuiTableRowCell, - KuiTableRow -} from '@kbn/ui-framework/components'; -import { MetricCell, OfflineCell } from 'plugins/monitoring/components/elasticsearch/node_listing/cells'; -import { NodeStatusIcon } from 'plugins/monitoring/components/elasticsearch/node/status_icon'; -import { Tooltip } from 'plugins/monitoring/components/tooltip'; -import { MonitoringTable } from 'plugins/monitoring/components/table'; -import { extractIp } from 'plugins/monitoring/lib/extract_ip'; -import { SORT_ASCENDING } from '../../../../common/constants'; -import { - EuiLink, -} from '@elastic/eui'; - -const filterFields = [ 'node.name', 'status', 'type', 'transport_address' ]; -const getColumns = showCgroupMetricsElasticsearch => { - const cols = []; - cols.push({ title: 'Name', sortKey: 'node.name', sortOrder: SORT_ASCENDING }); - cols.push({ title: 'Status', sortKey: 'online' }); - if (showCgroupMetricsElasticsearch) { - cols.push({ title: 'CPU Usage', sortKey: 'node_cgroup_quota.lastVal' }); - cols.push({ title: 'CPU Throttling', sortKey: 'node_cgroup_throttled.lastVal' }); - } else { - cols.push({ title: 'CPU Usage', sortKey: 'node_cpu_utilization.lastVal' }); - cols.push({ title: 'Load Average', sortKey: 'node_load_average.lastVal' }); - } - cols.push({ title: 'JVM Memory', sortKey: 'node_jvm_mem_percent.lastVal' }); - cols.push({ title: 'Disk Free Space', sortKey: 'node_free_space.lastVal' }); - cols.push({ title: 'Shards', sortKey: 'shardCount' }); - return cols; -}; -const nodeRowFactory = (scope, kbnUrl, showCgroupMetricsElasticsearch) => { - return class NodeRow extends React.Component { - constructor(props) { - super(props); - this.goToNode = this.goToNode.bind(this); - } - goToNode() { - scope.$evalAsync(() => { - kbnUrl.changePath(`/elasticsearch/nodes/${this.props.resolver}`); - }); - } - isOnline() { - return this.props.status === 'Online'; - } - getCpuComponents() { - const isOnline = this.isOnline(); - if (showCgroupMetricsElasticsearch) { - return [ - , - , - ]; - } - return [ - , - , - ]; - } - getShardCount() { - if (this.isOnline()) { - return ( - -
- {get(this.props, 'shardCount')} -
-
- ); - } - return ; - } - render() { - const isOnline = this.isOnline(); - return ( - - -
- - - -   - - {this.props.name} - -
-
{extractIp(this.props.transport_address)}
-
- -
-   - {this.props.status} -
-
- {this.getCpuComponents()} - - - {this.getShardCount()} -
- ); - } - }; -}; - -// change the node to actually display the name -const uiModule = uiModules.get('monitoring/directives', []); -uiModule.directive('monitoringNodesListing', ($injector) => { - const kbnUrl = $injector.get('kbnUrl'); - const showCgroupMetricsElasticsearch = $injector.get('showCgroupMetricsElasticsearch'); - const columns = getColumns(showCgroupMetricsElasticsearch); - - return { - restrict: 'E', - scope: { - nodes: '=', - pageIndex: '=', - filterText: '=', - sortKey: '=', - sortOrder: '=', - onNewState: '=', - }, - link(scope, $el) { - - scope.$watch('nodes', (nodes = []) => { - const nodesTable = ( - - ); - render(nodesTable, $el[0]); - }); - - } - }; -}); diff --git a/x-pack/plugins/monitoring/public/directives/elasticsearch/node_summary/index.html b/x-pack/plugins/monitoring/public/directives/elasticsearch/node_summary/index.html deleted file mode 100644 index 9dcfb588dd3c11..00000000000000 --- a/x-pack/plugins/monitoring/public/directives/elasticsearch/node_summary/index.html +++ /dev/null @@ -1,42 +0,0 @@ -
-
-
- {{ node.transport_address|extractIp }} -
-
- JVM Heap: - {{ node.usedHeap|formatMetric:'0,0.[00]':'%' }} -
-
- Free Disk Space: - {{ node.freeSpace|formatMetric:'0.0 b' }} -
-
- Documents: - {{ node.documents|formatMetric:'0.[0]a' }} -
-
- Data: {{ node.dataSize|formatMetric:'0.0 b' }} -
-
- Indices: - {{ node.indexCount|formatMetric:'0,0' }} -
-
- Shards: - {{ node.totalShards|formatMetric:'0,0' }} -
-
- Type: - {{ node.nodeTypeLabel }} -
-
- Health: - - {{ node.status|capitalize }} -
-
-
diff --git a/x-pack/plugins/monitoring/public/directives/elasticsearch/node_summary/index.js b/x-pack/plugins/monitoring/public/directives/elasticsearch/node_summary/index.js index bc1251c9809a8a..638e2423233ef4 100644 --- a/x-pack/plugins/monitoring/public/directives/elasticsearch/node_summary/index.js +++ b/x-pack/plugins/monitoring/public/directives/elasticsearch/node_summary/index.js @@ -4,16 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; +import { render } from 'react-dom'; import { uiModules } from 'ui/modules'; -import template from './index.html'; +import { NodeDetailStatus } from 'plugins/monitoring/components/elasticsearch/node_detail_status'; const uiModule = uiModules.get('monitoring/directives', []); uiModule.directive('monitoringNodeSummary', () => { return { restrict: 'E', - template: template, scope: { node: '=' + }, + link(scope, $el) { + scope.$watch('node', node => { + render(, $el[0]); + }); } }; }); diff --git a/x-pack/plugins/monitoring/public/directives/kibana/cluster_status/index.html b/x-pack/plugins/monitoring/public/directives/kibana/cluster_status/index.html deleted file mode 100644 index d8edd487a7499e..00000000000000 --- a/x-pack/plugins/monitoring/public/directives/kibana/cluster_status/index.html +++ /dev/null @@ -1,40 +0,0 @@ -
-
-
Instances: - - {{ status.count }} - -
-
Memory: - - {{ status.memory_size|formatNumber:'byte' }} / {{ status.memory_limit|formatNumber:'byte' }} - -
-
Requests: - - {{ status.requests_total }} - -
-
Connections: - - {{ status.concurrent_connections|formatNumber:'int_commas' }} - -
-
Max. Response Time: - - {{ status.response_time_max }} ms - -
-
- Health: - - {{ status.status|capitalize }} -
-
-
diff --git a/x-pack/plugins/monitoring/public/directives/kibana/cluster_status/index.js b/x-pack/plugins/monitoring/public/directives/kibana/cluster_status/index.js index 92da0af8b6e936..1582966b5951d9 100644 --- a/x-pack/plugins/monitoring/public/directives/kibana/cluster_status/index.js +++ b/x-pack/plugins/monitoring/public/directives/kibana/cluster_status/index.js @@ -4,16 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; +import { render } from 'react-dom'; import { uiModules } from 'ui/modules'; -import template from './index.html'; +import { ClusterStatus } from 'plugins/monitoring/components/kibana/cluster_status'; const uiModule = uiModules.get('monitoring/directives', []); uiModule.directive('monitoringClusterStatusKibana', () => { return { restrict: 'E', - template, scope: { - status: '=' - } + status: '=', + }, + link(scope, $el) { + scope.$watch('status', status => { + render(, $el[0]); + }); + }, }; }); diff --git a/x-pack/plugins/monitoring/public/directives/kibana/summary/index.html b/x-pack/plugins/monitoring/public/directives/kibana/summary/index.html deleted file mode 100644 index e35d727cd52e14..00000000000000 --- a/x-pack/plugins/monitoring/public/directives/kibana/summary/index.html +++ /dev/null @@ -1,27 +0,0 @@ -
-
-
- {{ kibana.transport_address }} -
-
OS Free Memory: - {{ kibana.os_memory_free|formatNumber:'byte' }} -
-
Version: - {{ kibana.version }} -
-
Uptime: - {{ kibana.uptime|formatNumber:'time_since' }} -
-
- Health: - - {{ kibana.status|capitalize }} -
-
-
diff --git a/x-pack/plugins/monitoring/public/directives/kibana/summary/index.js b/x-pack/plugins/monitoring/public/directives/kibana/summary/index.js index b11066a951f953..1077ed579420a0 100644 --- a/x-pack/plugins/monitoring/public/directives/kibana/summary/index.js +++ b/x-pack/plugins/monitoring/public/directives/kibana/summary/index.js @@ -4,16 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; +import { render } from 'react-dom'; import { uiModules } from 'ui/modules'; -import template from './index.html'; +import { DetailStatus } from 'plugins/monitoring/components/kibana/detail_status'; const uiModule = uiModules.get('monitoring/directives', []); uiModule.directive('monitoringKibanaSummary', () => { return { restrict: 'E', - template: template, scope: { kibana: '=' + }, + link(scope, $el) { + scope.$watch('kibana', kibana => { + render(, $el[0]); + }); } }; }); diff --git a/x-pack/plugins/monitoring/public/directives/logstash/cluster_status/index.html b/x-pack/plugins/monitoring/public/directives/logstash/cluster_status/index.html deleted file mode 100644 index 718df830177e3f..00000000000000 --- a/x-pack/plugins/monitoring/public/directives/logstash/cluster_status/index.html +++ /dev/null @@ -1,19 +0,0 @@ -
-
-
Nodes: - {{ status.node_count }} -
-
Memory: - {{ status.avg_memory_used|formatNumber:'byte' }} / {{ status.avg_memory|formatNumber:'byte' }} -
-
Events Received: - {{ status.events_in_total|formatNumber:'0.[0]a' }} -
-
Events Emitted: - {{ status.events_out_total|formatNumber:'0.[0]a' }} -
-
-
diff --git a/x-pack/plugins/monitoring/public/directives/logstash/cluster_status/index.js b/x-pack/plugins/monitoring/public/directives/logstash/cluster_status/index.js index 6ed47b9edb6f15..e3c0f2dac08d71 100644 --- a/x-pack/plugins/monitoring/public/directives/logstash/cluster_status/index.js +++ b/x-pack/plugins/monitoring/public/directives/logstash/cluster_status/index.js @@ -4,16 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; +import { render } from 'react-dom'; import { uiModules } from 'ui/modules'; -import template from './index.html'; +import { ClusterStatus } from 'plugins/monitoring/components/logstash/cluster_status'; const uiModule = uiModules.get('monitoring/directives', []); uiModule.directive('monitoringClusterStatusLogstash', () => { return { restrict: 'E', - template, scope: { status: '=' + }, + link(scope, $el) { + scope.$watch('status', status => { + render(, $el[0]); + }); } }; }); diff --git a/x-pack/plugins/monitoring/public/directives/logstash/node_summary/index.html b/x-pack/plugins/monitoring/public/directives/logstash/node_summary/index.html deleted file mode 100644 index b69353e13d2052..00000000000000 --- a/x-pack/plugins/monitoring/public/directives/logstash/node_summary/index.html +++ /dev/null @@ -1,31 +0,0 @@ -
-
-
- {{ logstash.http_address }} -
-
Events Received: - {{ logstash.events.in|formatNumber:'0.[0]a' }} -
-
Events Emitted: - {{ logstash.events.out|formatNumber:'0.[0]a' }} -
-
Config Reloads: - {{ logstash.reloads.successes }} -
-
Pipeline Workers: - {{ logstash.pipeline.workers }} -
-
Batch Size: - {{ logstash.pipeline.batch_size }} -
-
Queue Type: - {{ logstash.queue_type }} -
-
Logstash: - {{ logstash.version }} -
-
Uptime: - {{ logstash.uptime|formatNumber:'time_since' }} -
-
-
diff --git a/x-pack/plugins/monitoring/public/directives/logstash/node_summary/index.js b/x-pack/plugins/monitoring/public/directives/logstash/node_summary/index.js index b7e10dbce24e25..b7d13f61afaa53 100644 --- a/x-pack/plugins/monitoring/public/directives/logstash/node_summary/index.js +++ b/x-pack/plugins/monitoring/public/directives/logstash/node_summary/index.js @@ -4,16 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ -import template from './index.html'; +import React from 'react'; +import { render } from 'react-dom'; import { uiModules } from 'ui/modules'; +import { DetailStatus } from 'plugins/monitoring/components/logstash/detail_status'; const uiModule = uiModules.get('monitoring/directives', []); uiModule.directive('monitoringLogstashNodeSummary', () => { return { restrict: 'E', - template: template, scope: { logstash: '=' + }, + link(scope, $el) { + scope.$watch('logstash', logstash => { + render(, $el[0]); + }); } }; }); diff --git a/x-pack/plugins/monitoring/public/less/views/license.less b/x-pack/plugins/monitoring/public/less/views/license.less index ffb4a4c81d1876..e813394e310aee 100644 --- a/x-pack/plugins/monitoring/public/less/views/license.less +++ b/x-pack/plugins/monitoring/public/less/views/license.less @@ -1,6 +1,23 @@ @import (reference) '~ui/styles/variables/colors'; -@import '~plugins/license_management/styles/main'; .tab-license { background: @globalColorLightestGray; } + +.licenseFeature { + flex-grow: 1; + background: @globalColorLightestGray; +} + +.licenseManagement__pageBody { + padding-top: 24px; + min-height: auto; +} + +.licenseManagement__pageContent { + flex-grow: 0; // Temporary fix for EUI bug. +} + +.licenseManagement__contain { + margin: auto; +} diff --git a/x-pack/plugins/monitoring/public/register_feature.js b/x-pack/plugins/monitoring/public/register_feature.js index 245695e5c235b3..ccfd85f9f67b3b 100644 --- a/x-pack/plugins/monitoring/public/register_feature.js +++ b/x-pack/plugins/monitoring/public/register_feature.js @@ -15,7 +15,7 @@ if (chrome.getInjected('monitoringUiEnabled')) { id: 'monitoring', title: 'Monitoring', description: 'Track the real-time health and performance of your Elastic Stack.', - icon: '/plugins/kibana/assets/app_monitoring.svg', + icon: 'monitoringApp', path: '/app/monitoring', showOnHomePage: true, category: FeatureCatalogueCategory.ADMIN diff --git a/x-pack/plugins/monitoring/public/views/base_controller.js b/x-pack/plugins/monitoring/public/views/base_controller.js index a7b45e9fcd0ed6..59502b41a42098 100644 --- a/x-pack/plugins/monitoring/public/views/base_controller.js +++ b/x-pack/plugins/monitoring/public/views/base_controller.js @@ -40,19 +40,27 @@ export class MonitoringViewBaseController { /** * Create a view controller * @param {String} title - Title of the page - * @param {String} api - Back-end API endpoint to poll for getting the page data using POST and time range data in the body. - * Whenever possible, use this method for data polling rather than supply the getPageData param. - * @param {Function} getPageData - (Optional) Function to fetch page data, if simply passing the API string isn't workable. + * @param {String} api - Back-end API endpoint to poll for getting the page + * data using POST and time range data in the body. Whenever possible, use + * this method for data polling rather than supply the getPageData param. + * @param {Function} apiUrlFn - Function that returns a string for the back-end + * API endpoint, in case the string has dynamic query parameters (e.g. + * show_system_indices) rather than supply the getPageData param. + * @param {Function} getPageData - (Optional) Function to fetch page data, if + * simply passing the API string isn't workable. * @param {Object} defaultData - Initial model data to populate - * @param {String} reactNodeId - DOM element ID of the element for mounting the view's main React component + * @param {String} reactNodeId - DOM element ID of the element for mounting + * the view's main React component * @param {Service} $injector - Angular dependency injection service * @param {Service} $scope - Angular view data binding service * @param {Boolean} options.enableTimeFilter - Whether to show the time filter - * @param {Boolean} options.enableAutoRefresh - Whether to show the auto refresh control + * @param {Boolean} options.enableAutoRefresh - Whether to show the auto + * refresh control */ constructor({ title = '', api = '', + apiUrlFn, getPageData: _getPageData = getPageData, defaultData, reactNodeId = null, // WIP: https://github.com/elastic/x-pack-kibana/issues/5198 @@ -88,7 +96,8 @@ export class MonitoringViewBaseController { } this.updateData = () => { - return _getPageData($injector, api) + const _api = apiUrlFn ? apiUrlFn() : api; + return _getPageData($injector, _api) .then(pageData => { this._isDataInitialized = true; // render will replace loading screen with the react component this.data = pageData; // update the view's data with the fetch result diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/indices/get_page_data.js b/x-pack/plugins/monitoring/public/views/elasticsearch/indices/get_page_data.js deleted file mode 100644 index dc9297bf4210c8..00000000000000 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/indices/get_page_data.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler'; - -export function getPageData($injector) { - const globalState = $injector.get('globalState'); - const timefilter = $injector.get('timefilter'); - const $http = $injector.get('$http'); - const features = $injector.get('features'); - - const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/elasticsearch/indices`; - const showSystemIndices = features.isEnabled('showSystemIndices', false); - const timeBounds = timefilter.getBounds(); - - /* TODO: get `pageIndex`, `filterText`, `sortKey`, `sortOrder` through `getLocalStorageData` - * and send params through API */ - - return $http.post(url, { - showSystemIndices, - ccs: globalState.ccs, - timeRange: { - min: timeBounds.min.toISOString(), - max: timeBounds.max.toISOString() - } - }) - .then(response => response.data) - .then(data => { - data.rows.forEach(row => { - // calculate a numerical field to help sorting by status - // this allows default sort to show red, then yellow, then green - switch (row.status) { - case 'Deleted': - row.statusSort = 0; - break; - case 'green': - row.statusSort = 1; - break; - case 'yellow': - row.statusSort = 2; - break; - default: - row.statusSort = 3; - } - }); - return data; - }) - .catch((err) => { - const Private = $injector.get('Private'); - const ajaxErrorHandlers = Private(ajaxErrorHandlersProvider); - return ajaxErrorHandlers(err); - }); -} diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/indices/index.html b/x-pack/plugins/monitoring/public/views/elasticsearch/indices/index.html index 0ef920779dcfdc..97c76e2c3ad7d8 100644 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/indices/index.html +++ b/x-pack/plugins/monitoring/public/views/elasticsearch/indices/index.html @@ -3,18 +3,5 @@ name="indices" data-test-subj="elasticsearchIndicesListingPage" > - -
-

Indices

- -
+
diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/indices/index.js b/x-pack/plugins/monitoring/public/views/elasticsearch/indices/index.js index 3b0d75365aeed5..b71b8f43814f66 100644 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/indices/index.js +++ b/x-pack/plugins/monitoring/public/views/elasticsearch/indices/index.js @@ -4,53 +4,70 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; import { find } from 'lodash'; import uiRoutes from 'ui/routes'; import { routeInitProvider } from 'plugins/monitoring/lib/route_init'; import { MonitoringViewBaseTableController } from '../../'; -import { getPageData } from './get_page_data'; +import { ElasticsearchIndices } from '../../../components'; import template from './index.html'; uiRoutes.when('/elasticsearch/indices', { template, resolve: { - clusters: function (Private) { + clusters(Private) { const routeInit = Private(routeInitProvider); return routeInit(); - }, - pageData: getPageData + } }, - controllerAs: 'esIndices', - controller: class EsIndicesList extends MonitoringViewBaseTableController { - + controllerAs: 'elasticsearchIndices', + controller: class ElasticsearchIndicesController extends MonitoringViewBaseTableController { constructor($injector, $scope) { + const $route = $injector.get('$route'); + const globalState = $injector.get('globalState'); + const features = $injector.get('features'); + + const { cluster_uuid: clusterUuid } = globalState; + $scope.cluster = find($route.current.locals.clusters, { cluster_uuid: clusterUuid }); + + let showSystemIndices = features.isEnabled('showSystemIndices', false); + super({ title: 'Elasticsearch - Indices', storageKey: 'elasticsearch.indices', - getPageData, + apiUrlFn: () => `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch/indices?show_system_indices=${showSystemIndices}`, + reactNodeId: 'elasticsearchIndicesReact', + defaultData: {}, + $scope, + $injector, $scope, $injector }); - const $route = $injector.get('$route'); - this.data = $route.current.locals.pageData; - const globalState = $injector.get('globalState'); - $scope.cluster = find($route.current.locals.clusters, { cluster_uuid: globalState.cluster_uuid }); - - // used in table toolbar - const features = $injector.get('features'); - this.showSystemIndices = features.isEnabled('showSystemIndices', false); - // for binding - this.toggleShowSystemIndices = isChecked => { + const toggleShowSystemIndices = isChecked => { // flip the boolean - this.showSystemIndices = isChecked; + showSystemIndices = isChecked; // preserve setting in localStorage features.update('showSystemIndices', isChecked); // update the page (resets pagination and sorting) this.updateData(); }; - } + $scope.$watch(() => this.data, data => { + this.renderReact(data); + }); + + this.renderReact = ({ clusterStatus, indices }) => { + super.renderReact( + + ); + }; + } } }); diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/get_page_data.js b/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/get_page_data.js deleted file mode 100644 index 019354f8728ad9..00000000000000 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/get_page_data.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler'; - -export function getPageData($injector) { - const $http = $injector.get('$http'); - const globalState = $injector.get('globalState'); - const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/elasticsearch/nodes`; - const timefilter = $injector.get('timefilter'); - const timeBounds = timefilter.getBounds(); - - const createRow = rowData => { - if (!rowData) { - return null; - } - return { - status: rowData.isOnline ? 'Online' : 'Offline', - ...rowData - }; - }; - - return $http.post(url, { - ccs: globalState.ccs, - timeRange: { - min: timeBounds.min.toISOString(), - max: timeBounds.max.toISOString() - } - }) - .then(response => { - return { - clusterStatus: response.data.clusterStatus, - nodes: response.data.nodes.map(createRow) - }; - }) - .catch((err) => { - const Private = $injector.get('Private'); - const ajaxErrorHandlers = Private(ajaxErrorHandlersProvider); - return ajaxErrorHandlers(err); - }); -} diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.html b/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.html index 82397bbe4c0280..4879ca6acae20c 100644 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.html +++ b/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.html @@ -3,16 +3,5 @@ name="nodes" data-test-subj="elasticsearchNodesListingPage" > - -
-

Elasticsearch Nodes

- -
+
diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js b/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js index 5e04e7bbf7832c..295ad6d1d36a8a 100644 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js +++ b/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js @@ -4,39 +4,56 @@ * you may not use this file except in compliance with the Elastic License. */ +import React from 'react'; import { find } from 'lodash'; import uiRoutes from 'ui/routes'; +import template from './index.html'; import { routeInitProvider } from 'plugins/monitoring/lib/route_init'; import { MonitoringViewBaseTableController } from '../../'; -import { getPageData } from './get_page_data'; -import template from './index.html'; +import { ElasticsearchNodes } from '../../../components'; uiRoutes.when('/elasticsearch/nodes', { template, resolve: { - clusters: function (Private) { + clusters(Private) { const routeInit = Private(routeInitProvider); return routeInit(); - }, - pageData: getPageData + } }, - controllerAs: 'esNodes', - controller: class EsNodesList extends MonitoringViewBaseTableController { - + controllerAs: 'elasticsearchNodes', + controller: class ElasticsearchNodesController extends MonitoringViewBaseTableController { constructor($injector, $scope) { + const $route = $injector.get('$route'); + const globalState = $injector.get('globalState'); + const showCgroupMetricsElasticsearch = $injector.get('showCgroupMetricsElasticsearch'); + + $scope.cluster = find($route.current.locals.clusters, { + cluster_uuid: globalState.cluster_uuid + }); + super({ title: 'Elasticsearch - Nodes', storageKey: 'elasticsearch.nodes', - getPageData, + api: `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/elasticsearch/nodes`, + reactNodeId: 'elasticsearchNodesReact', + defaultData: {}, $scope, $injector }); - const $route = $injector.get('$route'); - this.data = $route.current.locals.pageData; - const globalState = $injector.get('globalState'); - $scope.cluster = find($route.current.locals.clusters, { cluster_uuid: globalState.cluster_uuid }); - } + $scope.$watch(() => this.data, data => { + this.renderReact(data); + }); + this.renderReact = ({ clusterStatus, nodes }) => { + super.renderReact( + + ); + }; + } } }); diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/classes/__tests__/collector_set.js b/x-pack/plugins/monitoring/server/kibana_monitoring/classes/__tests__/collector_set.js new file mode 100644 index 00000000000000..7fa677a0ce0a97 --- /dev/null +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/classes/__tests__/collector_set.js @@ -0,0 +1,168 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { identity, noop } from 'lodash'; +import sinon from 'sinon'; +import expect from 'expect.js'; +import { Collector } from '../collector'; +import { CollectorSet } from '../collector_set'; + +const DEBUG_LOG = [ 'debug', 'monitoring-ui', 'kibana-monitoring' ]; +const INFO_LOG = [ 'info', 'monitoring-ui', 'kibana-monitoring' ]; + +const COLLECTOR_INTERVAL = 10000; +const CHECK_DELAY = 100; // can be lower than COLLECTOR_INTERVAL because the collectors use fetchAfterInit + +describe('CollectorSet', () => { + describe('registers a collector set and runs lifecycle events', () => { + let server; + let init; + let cleanup; + let fetch; + beforeEach(() => { + server = { + log: sinon.spy() + }; + init = noop; + cleanup = noop; + fetch = noop; + }); + + it('should throw an error if non-Collector type of object is registered', () => { + const collectors = new CollectorSet(server, { + interval: COLLECTOR_INTERVAL, + combineTypes: identity, + onPayload: identity + }); + + const registerPojo = () => { + collectors.register({ + type: 'type_collector_test', + fetchAfterInit: true, + init, + fetch, + cleanup + }); + }; + + expect(registerPojo).to.throwException(({ message }) => { + expect(message).to.be('CollectorSet can only have Collector instances registered'); + }); + }); + + it('should skip bulk upload if payload is empty', (done) => { + const collectors = new CollectorSet(server, { + interval: COLLECTOR_INTERVAL, + combineTypes: identity, + onPayload: identity + }); + + collectors.register(new Collector(server, { + type: 'type_collector_test', + fetchAfterInit: true, + init, + fetch, + cleanup + })); + + collectors.start(); + + // allow interval to tick a few times + setTimeout(() => { + collectors.cleanup(); + + expect(server.log.calledWith(INFO_LOG, 'Starting all stats collectors')).to.be(true); + expect(server.log.calledWith(DEBUG_LOG, 'Initializing type_collector_test collector')).to.be(true); + expect(server.log.calledWith(DEBUG_LOG, 'Fetching data from type_collector_test collector')).to.be(true); + expect(server.log.calledWith(DEBUG_LOG, 'Skipping bulk uploading of an empty stats payload')).to.be(true); // proof of skip + expect(server.log.calledWith(INFO_LOG, 'Stopping all stats collectors')).to.be(true); + expect(server.log.calledWith(DEBUG_LOG, 'Running type_collector_test cleanup')).to.be(true); + + done(); // for async exit + }, CHECK_DELAY); + }); + + it('should run the bulk upload handler', (done) => { + const combineTypes = sinon.spy(data => { + return [ + data[0][0], + { ...data[0][1], combined: true } + ]; + }); + const onPayload = sinon.spy(); + + const collectors = new CollectorSet(server, { + interval: COLLECTOR_INTERVAL, + combineTypes, + onPayload + }); + + fetch = () => ({ testFetch: true }); + collectors.register(new Collector(server, { + type: 'type_collector_test', + fetchAfterInit: true, + init, + fetch, + cleanup + })); + + collectors.start(); + + // allow interval to tick a few times + setTimeout(() => { + collectors.cleanup(); + + expect(server.log.calledWith(INFO_LOG, 'Starting all stats collectors')).to.be(true); + expect(server.log.calledWith(DEBUG_LOG, 'Initializing type_collector_test collector')).to.be(true); + expect(server.log.calledWith(DEBUG_LOG, 'Fetching data from type_collector_test collector')).to.be(true); + expect(server.log.calledWith(DEBUG_LOG, 'Uploading bulk stats payload to the local cluster')).to.be(true); + expect(server.log.calledWith(INFO_LOG, 'Stopping all stats collectors')).to.be(true); + expect(server.log.calledWith(DEBUG_LOG, 'Running type_collector_test cleanup')).to.be(true); + + // un-flattened + expect(combineTypes.getCall(0).args[0]).to.eql( + [ [ { index: { _type: 'type_collector_test' } }, { testFetch: true } ] ] + ); + + // flattened and altered + expect(onPayload.getCall(0).args[0]).to.eql( + [ { index: { _type: 'type_collector_test' } }, { testFetch: true, combined: true } ] + ); + + done(); // for async exit + }, CHECK_DELAY); + }); + + it('should log the info-level status of stopping and restarting', (done) => { + const collectors = new CollectorSet(server, { + interval: COLLECTOR_INTERVAL, + combineTypes: identity, + onPayload: identity + }); + + collectors.register(new Collector(server, { + type: 'type_collector_test', + fetchAfterInit: true, + init, + fetch, + cleanup + })); + + collectors.start(); + expect(server.log.calledWith(INFO_LOG, 'Starting all stats collectors')).to.be(true); + + collectors.cleanup(); + expect(server.log.calledWith(INFO_LOG, 'Stopping all stats collectors')).to.be(true); + + collectors.start(); + expect(server.log.calledWith(INFO_LOG, 'Starting all stats collectors')).to.be(true); + + // exit + collectors.cleanup(); + done(); + }); + }); +}); diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/classes/collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/classes/collector.js new file mode 100644 index 00000000000000..c7cf9e756e1524 --- /dev/null +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/classes/collector.js @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getCollectorLogger } from '../lib'; + +export class Collector { + /* + * @param {Object} server - server object + * @param {String} properties.type - property name as the key for the data + * @param {Function} properties.init (optional) - initialization function + * @param {Function} properties.fetch - function to query data + * @param {Function} properties.cleanup (optional) - cleanup function + * @param {Boolean} properties.fetchAfterInit (optional) - if collector should fetch immediately after init + */ + constructor(server, { type, init, fetch, cleanup, fetchAfterInit }) { + this.type = type; + this.init = init; + this.fetch = fetch; + this.cleanup = cleanup; + this.fetchAfterInit = fetchAfterInit; + + this.log = getCollectorLogger(server); + } +} diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/type_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/classes/collector_set.js similarity index 57% rename from x-pack/plugins/monitoring/server/kibana_monitoring/lib/type_collector.js rename to x-pack/plugins/monitoring/server/kibana_monitoring/classes/collector_set.js index 1842d5ba28dd22..285f08e5106c8c 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/type_collector.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/classes/collector_set.js @@ -5,29 +5,31 @@ */ import { flatten, isEmpty } from 'lodash'; -import { LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG } from '../../../common/constants'; import Promise from 'bluebird'; +import { getCollectorLogger } from '../lib'; +import { Collector } from './collector'; +import { UsageCollector } from './usage_collector'; -const LOGGING_TAGS = [LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG]; - -export class TypeCollector { +/* + * A collector object has types registered into it with the register(type) + * function. Each type that gets registered defines how to fetch its own data + * and combine it into a unified payload for bulk upload. + */ +export class CollectorSet { /* - * @param options.interval {Number} in milliseconds - * @param options.logger {Function} - * @param options.combineTypes {Function} - * @param options.onPayload {Function} + * @param {Object} server - server object + * @param {Number} options.interval - in milliseconds + * @param {Function} options.combineTypes + * @param {Function} options.onPayload */ - constructor({ interval, logger, combineTypes, onPayload }) { + constructor(server, { interval, combineTypes, onPayload }) { this._collectors = []; this._timer = null; if (typeof interval !== 'number') { throw new Error('interval number of milliseconds is required'); } - if (typeof logger !== 'function') { - throw new Error('Logger function is required'); - } if (typeof combineTypes !== 'function') { throw new Error('combineTypes function is required'); } @@ -35,11 +37,7 @@ export class TypeCollector { throw new Error('onPayload function is required'); } - this._log = { - debug: message => logger(['debug', ...LOGGING_TAGS], message), - info: message => logger(['info', ...LOGGING_TAGS], message), - warn: message => logger(['warning', ...LOGGING_TAGS], message) - }; + this._log = getCollectorLogger(server); this._interval = interval; this._combineTypes = combineTypes; @@ -47,15 +45,14 @@ export class TypeCollector { } /* - * @param {Object} collectorOptions (required) - * Fields: - * - type {String} - * - init {Function} (optional) - * - fetch {Function} - * - cleanup {Function} (optional) + * @param collector {Collector} collector object */ - register(collectorOptions) { - this._collectors.push(collectorOptions); + register(collector) { + // check instanceof + if (!(collector instanceof Collector)) { + throw new Error('CollectorSet can only have Collector instances registered'); + } + this._collectors.push(collector); } /* @@ -64,7 +61,7 @@ export class TypeCollector { */ start() { const initialCollectors = []; - this._log.info(`Starting all Kibana monitoring collectors`); + this._log.info(`Starting all stats collectors`); this._collectors.forEach(collector => { if (collector.init) { @@ -72,10 +69,7 @@ export class TypeCollector { collector.init(); } - if (collector.setLogger) { - this._log.debug(`Setting logger for ${collector.type} collector`); - collector.setLogger(this._log); - } + this._log.debug(`Setting logger for ${collector.type} collector`); if (collector.fetchAfterInit) { initialCollectors.push(collector); @@ -106,15 +100,15 @@ export class TypeCollector { if (payload.length > 0) { try { - const combinedData = this._combineTypes(payload); - this._log.debug(`Uploading bulk Kibana monitoring payload`); + const combinedData = this._combineTypes(payload); // use the collector types combiner + this._log.debug(`Uploading bulk stats payload to the local cluster`); this._onPayload(flatten(combinedData)); } catch(err) { this._log.warn(err); - this._log.warn(`Unable to bulk upload the Kibana monitoring payload`); + this._log.warn(`Unable to bulk upload the stats payload to the local cluster`); } } else { - this._log.debug(`Skipping bulk uploading of empty Kibana monitoring payload`); + this._log.debug(`Skipping bulk uploading of an empty stats payload`); } } @@ -136,8 +130,26 @@ export class TypeCollector { }); } + async bulkFetchUsage() { + const usageCollectors = this._collectors.filter(c => c instanceof UsageCollector); + const bulk = await this._bulkFetch(usageCollectors); + + // summarize each type of stat + return bulk.reduce((accumulatedStats, currentStat) => { + /* Suffix removal is a temporary hack: some types have `_stats` suffix + * because of how monitoring bulk upload needed to combine types. It can + * be removed when bulk upload goes away + */ + const statType = currentStat.type.replace('_stats', ''); + return { + ...accumulatedStats, + [statType]: currentStat.result, + }; + }, {}); + } + cleanup() { - this._log.info(`Stopping all Kibana monitoring collectors`); + this._log.info(`Stopping all stats collectors`); // stop fetching clearInterval(this._timer); diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/classes/usage_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/classes/usage_collector.js new file mode 100644 index 00000000000000..97e10e1c5bf16e --- /dev/null +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/classes/usage_collector.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Collector } from './collector'; + +export class UsageCollector extends Collector { + constructor(server, properties) { + super(server, properties); + } +} diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_usage_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_kibana_usage_collector.js similarity index 82% rename from x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_usage_collector.js rename to x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_kibana_usage_collector.js index e74fd5e022ee90..27ce2c773eabb5 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_usage_collector.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_kibana_usage_collector.js @@ -6,10 +6,10 @@ import expect from 'expect.js'; import sinon from 'sinon'; -import { getUsageCollector } from '../get_usage_collector'; +import { getKibanaUsageCollector } from '../get_kibana_usage_collector'; import { callClusterFactory } from '../../../../../xpack_main'; -describe('getUsageCollector', () => { +describe('getKibanaUsageCollector', () => { let clusterStub; let serverStub; let callClusterStub; @@ -22,14 +22,15 @@ describe('getUsageCollector', () => { getCluster: sinon.stub() } }, - config: () => ({ get: sinon.stub() }) + config: () => ({ get: sinon.stub() }), + log: sinon.stub(), }; serverStub.plugins.elasticsearch.getCluster.withArgs('admin').returns(clusterStub); callClusterStub = callClusterFactory(serverStub).getCallClusterInternal(); }); it('correctly defines usage collector.', () => { - const usageCollector = getUsageCollector(serverStub, callClusterStub); + const usageCollector = getKibanaUsageCollector(serverStub, callClusterStub); expect(usageCollector.type).to.be('kibana'); expect(usageCollector.fetch).to.be.a(Function); @@ -44,7 +45,7 @@ describe('getUsageCollector', () => { } }); - const usageCollector = getUsageCollector(serverStub, callClusterStub); + const usageCollector = getKibanaUsageCollector(serverStub, callClusterStub); await usageCollector.fetch(); sinon.assert.calledOnce(clusterStub.callWithInternalUser); diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_reporting_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_reporting_collector.js deleted file mode 100644 index e6aa75e66aace7..00000000000000 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/__tests__/get_reporting_collector.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from 'expect.js'; -import sinon from 'sinon'; -import { getReportingCollector } from '../get_reporting_collector'; -import { callClusterFactory } from '../../../../../xpack_main'; - -describe('getReportingCollector', () => { - let clusterStub; - let serverStub; - let callClusterStub; - - beforeEach(() => { - clusterStub = { callWithInternalUser: sinon.stub().returns(Promise.resolve({})) }; - serverStub = { - plugins: { - elasticsearch: { getCluster: sinon.stub() }, - xpack_main: { - info: { - license: { getType: sinon.stub() }, - isAvailable() { return true; } - } - } - }, - config: () => ({ get: sinon.stub() }), - expose: sinon.stub(), - log: sinon.stub(), - }; - - serverStub.plugins.elasticsearch.getCluster.withArgs('admin').returns(clusterStub); - callClusterStub = callClusterFactory(serverStub).getCallClusterInternal(); - }); - - it('correctly defines reporting collector.', () => { - const reportingCollector = getReportingCollector(serverStub, callClusterStub); - - expect(reportingCollector.type).to.be('reporting_stats'); - expect(reportingCollector.fetch).to.be.a(Function); - }); -}); diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_usage_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_kibana_usage_collector.js similarity index 84% rename from x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_usage_collector.js rename to x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_kibana_usage_collector.js index 31270589e23916..304ac5643d7740 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_usage_collector.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_kibana_usage_collector.js @@ -6,6 +6,7 @@ import { get, snakeCase } from 'lodash'; import { KIBANA_USAGE_TYPE } from '../../../common/constants'; +import { UsageCollector } from '../classes/usage_collector'; const TYPES = [ 'dashboard', @@ -19,8 +20,8 @@ const TYPES = [ /** * Fetches saved object client counts by querying the saved object index */ -export function getUsageCollector(server, callCluster) { - return { +export function getKibanaUsageCollector(server, callCluster) { + return new UsageCollector(server, { type: KIBANA_USAGE_TYPE, async fetch() { const index = server.config().get('kibana.index'); @@ -52,9 +53,7 @@ export function getUsageCollector(server, callCluster) { return { index, - - // combine the bucketCounts and 0s for types that don't have documents - ...TYPES.reduce((acc, type) => ({ + ...TYPES.reduce((acc, type) => ({ // combine the bucketCounts and 0s for types that don't have documents ...acc, [snakeCase(type)]: { total: bucketCounts[type] || 0 @@ -62,5 +61,5 @@ export function getUsageCollector(server, callCluster) { }), {}) }; } - }; + }); } diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.js index 496468f07ceac6..f4ab40258aa8e2 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_ops_stats_collector.js @@ -6,6 +6,7 @@ import { KIBANA_STATS_TYPE } from '../../../common/constants'; import { opsBuffer } from './ops_buffer'; +import { Collector } from '../classes/collector'; /* * Initialize a collector for Kibana Ops Stats @@ -20,11 +21,6 @@ export function getOpsStatsCollector(server) { monitor.on('ops', onOps); }; - let _log; - const setLogger = logger => { - _log = logger; - }; - const cleanup = () => { if (monitor) { monitor.removeListener('ops', onOps); @@ -34,7 +30,7 @@ export function getOpsStatsCollector(server) { // This needs to be removed once the FIXME for 1301 is fixed // `process` is a NodeJS global, and is always available without using require/import process.on('SIGHUP', () => { - _log.info('Re-initializing Kibana Monitoring due to SIGHUP'); + this.log.info('Re-initializing Kibana Monitoring due to SIGHUP'); /* This timeout is a temporary stop-gap until collecting stats is not bound to even-better * and collecting stats is not interfered by logging configuration reloading * Related to https://github.com/elastic/x-pack-kibana/issues/1301 @@ -42,16 +38,15 @@ export function getOpsStatsCollector(server) { setTimeout(() => { cleanup(); init(); - _log.info('Re-initialized Kibana Monitoring due to SIGHUP'); + this.log.info('Re-initialized Kibana Monitoring due to SIGHUP'); }, 5 * 1000); // wait 5 seconds to avoid race condition with reloading logging configuration }); - return { + return new Collector(server, { type: KIBANA_STATS_TYPE, init, - setLogger, fetch: buffer.flush, fetchAfterInit: true, cleanup - }; + }); } diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_reporting_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_reporting_collector.js deleted file mode 100644 index 7bc83cc9c863ed..00000000000000 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_reporting_collector.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { KIBANA_REPORTING_TYPE } from '../../../common/constants'; -import { getReportingUsage } from '../../../../reporting'; - -export function getReportingCollector(server, callCluster) { - return { - type: KIBANA_REPORTING_TYPE, - fetch() { - return getReportingUsage(callCluster, server); - } - }; -} diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.js index bbdddeee0ade02..d3d791e3cebf5e 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/get_settings_collector.js @@ -5,9 +5,9 @@ */ import { get } from 'lodash'; - import { XPACK_DEFAULT_ADMIN_EMAIL_UI_SETTING } from '../../../../../server/lib/constants'; import { KIBANA_SETTINGS_TYPE } from '../../../common/constants'; +import { Collector } from '../classes/collector'; /* * Check if Cluster Alert email notifications is enabled in config @@ -58,36 +58,28 @@ export function getSettingsCollector(server) { const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); const config = server.config(); - let _log; - const setLogger = logger => { - _log = logger; - }; - - const fetch = async () => { - let kibanaSettingsData; - const defaultAdminEmail = await checkForEmailValue(config, callWithInternalUser); - - // skip everything if defaultAdminEmail === undefined - if (defaultAdminEmail || (defaultAdminEmail === null && shouldUseNull)) { - kibanaSettingsData = { - xpack: { - default_admin_email: defaultAdminEmail - } - }; - _log.debug(`[${defaultAdminEmail}] default admin email setting found, sending [${KIBANA_SETTINGS_TYPE}] monitoring document.`); - } else { - _log.debug(`not sending [${KIBANA_SETTINGS_TYPE}] monitoring document because [${defaultAdminEmail}] is null or invalid.`); - } - - // remember the current email so that we can mark it as successful if the bulk does not error out - shouldUseNull = !!defaultAdminEmail; - - return kibanaSettingsData; - }; - - return { + return new Collector(server, { type: KIBANA_SETTINGS_TYPE, - setLogger, - fetch - }; + async fetch() { + let kibanaSettingsData; + const defaultAdminEmail = await checkForEmailValue(config, callWithInternalUser); + + // skip everything if defaultAdminEmail === undefined + if (defaultAdminEmail || (defaultAdminEmail === null && shouldUseNull)) { + kibanaSettingsData = { + xpack: { + default_admin_email: defaultAdminEmail + } + }; + this.log.debug(`[${defaultAdminEmail}] default admin email setting found, sending [${KIBANA_SETTINGS_TYPE}] monitoring document.`); + } else { + this.log.debug(`not sending [${KIBANA_SETTINGS_TYPE}] monitoring document because [${defaultAdminEmail}] is null or invalid.`); + } + + // remember the current email so that we can mark it as successful if the bulk does not error out + shouldUseNull = !!defaultAdminEmail; + + return kibanaSettingsData; + } + }); } diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/init_kibana_monitoring.js b/x-pack/plugins/monitoring/server/kibana_monitoring/create_collector_set.js similarity index 75% rename from x-pack/plugins/monitoring/server/kibana_monitoring/init_kibana_monitoring.js rename to x-pack/plugins/monitoring/server/kibana_monitoring/create_collector_set.js index 71127671015ac1..2edcad1fa2d152 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/init_kibana_monitoring.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/create_collector_set.js @@ -6,26 +6,30 @@ import { LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG, } from '../../common/constants'; import { monitoringBulk } from './lib/monitoring_bulk'; -import { startCollector } from './start_collector'; +import { startCollectorSet } from './start_collector_set'; /** * @param kbnServer {Object} manager of Kibana services - see `src/server/kbn_server` in Kibana core * @param server {Object} HapiJS server instance + * @return {Object} CollectorSet instance to be exposed at a higher level, for other plugins to register their own type collectors */ -export async function initKibanaMonitoring(kbnServer, server) { +export function createCollectorSet(kbnServer, server) { const mainXpackInfo = server.plugins.xpack_main.info; const mainMonitoring = mainXpackInfo.feature('monitoring'); + let collectorSet; + if (mainXpackInfo && mainMonitoring.isAvailable() && mainMonitoring.isEnabled()) { const client = server.plugins.elasticsearch.getCluster('admin').createClient({ plugins: [monitoringBulk] }); - - startCollector(kbnServer, server, client); + collectorSet = startCollectorSet(kbnServer, server, client); } else { server.log( ['error', LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG], 'Unable to retrieve X-Pack info from the admin cluster. Kibana monitoring will be disabled until Kibana is restarted.' ); } + + return collectorSet; } diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/index.js b/x-pack/plugins/monitoring/server/kibana_monitoring/index.js index a1d02ec335b004..a79c7aa2ecc113 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/index.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/index.js @@ -4,6 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -export { initKibanaMonitoring } from './init_kibana_monitoring'; -export { getUsageCollector } from './collectors/get_usage_collector'; -export { getReportingCollector } from './collectors/get_reporting_collector'; +export { createCollectorSet } from './create_collector_set'; +export { getKibanaUsageCollector } from './collectors/get_kibana_usage_collector'; +export { UsageCollector } from './classes/usage_collector'; diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/__tests__/type_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/__tests__/type_collector.js deleted file mode 100644 index 6072de9678035a..00000000000000 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/__tests__/type_collector.js +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { identity, noop } from 'lodash'; -import sinon from 'sinon'; -import expect from 'expect.js'; -import { TypeCollector } from '../type_collector'; - -const DEBUG_LOG = [ 'debug', 'monitoring-ui', 'kibana-monitoring' ]; -const INFO_LOG = [ 'info', 'monitoring-ui', 'kibana-monitoring' ]; - -const COLLECTOR_INTERVAL = 10000; -const CHECK_DELAY = 100; // can be lower than COLLECTOR_INTERVAL because the collectors use fetchAfterInit - -describe('TypeCollector', () => { - describe('registers a collector and runs lifecycle events', () => { - let log; - let init; - let cleanup; - let fetch; - beforeEach(() => { - log = sinon.spy(); - init = noop; - cleanup = noop; - fetch = noop; - }); - - it('for skipping bulk upload because payload is empty', (done) => { - const collector = new TypeCollector({ - interval: COLLECTOR_INTERVAL, - logger: log, - combineTypes: identity, - onPayload: identity - }); - - collector.register({ - type: 'type_collector_test', - fetchAfterInit: true, - init, - fetch, - cleanup - }); - - collector.start(); - - // allow interval to tick a few times - setTimeout(() => { - collector.cleanup(); - - expect(log.calledWith(INFO_LOG, 'Starting all Kibana monitoring collectors')).to.be(true); - expect(log.calledWith(DEBUG_LOG, 'Initializing type_collector_test collector')).to.be(true); - expect(log.calledWith(DEBUG_LOG, 'Fetching data from type_collector_test collector')).to.be(true); - expect(log.calledWith(DEBUG_LOG, 'Skipping bulk uploading of empty Kibana monitoring payload')).to.be(true); // proof of skip - expect(log.calledWith(INFO_LOG, 'Stopping all Kibana monitoring collectors')).to.be(true); - expect(log.calledWith(DEBUG_LOG, 'Running type_collector_test cleanup')).to.be(true); - - done(); // for async exit - }, CHECK_DELAY); - }); - - it('for running the bulk upload handler', (done) => { - const log = sinon.spy(); - const combineTypes = sinon.spy(data => { - return [ - data[0][0], - { ...data[0][1], combined: true } - ]; - }); - const onPayload = sinon.spy(); - - const collector = new TypeCollector({ - interval: COLLECTOR_INTERVAL, - logger: log, - combineTypes, - onPayload - }); - - fetch = () => ({ testFetch: true }); - collector.register({ - type: 'type_collector_test', - fetchAfterInit: true, - init, - fetch, - cleanup - }); - - collector.start(); - - // allow interval to tick a few times - setTimeout(() => { - collector.cleanup(); - - expect(log.calledWith(INFO_LOG, 'Starting all Kibana monitoring collectors')).to.be(true); - expect(log.calledWith(DEBUG_LOG, 'Initializing type_collector_test collector')).to.be(true); - expect(log.calledWith(DEBUG_LOG, 'Fetching data from type_collector_test collector')).to.be(true); - expect(log.calledWith(DEBUG_LOG, 'Uploading bulk Kibana monitoring payload')).to.be(true); - expect(log.calledWith(INFO_LOG, 'Stopping all Kibana monitoring collectors')).to.be(true); - expect(log.calledWith(DEBUG_LOG, 'Running type_collector_test cleanup')).to.be(true); - - // un-flattened - expect(combineTypes.getCall(0).args[0]).to.eql( - [ [ { index: { _type: 'type_collector_test' } }, { testFetch: true } ] ] - ); - - // flattened and altered - expect(onPayload.getCall(0).args[0]).to.eql( - [ { index: { _type: 'type_collector_test' } }, { testFetch: true, combined: true } ] - ); - - done(); // for async exit - }, CHECK_DELAY); - }); - - it('logs info-level status of stopping and restarting', (done) => { - const collector = new TypeCollector({ - interval: COLLECTOR_INTERVAL, - logger: log, - combineTypes: identity, - onPayload: identity - }); - - collector.register({ - type: 'type_collector_test', - fetchAfterInit: true, - init, - fetch, - cleanup - }); - - collector.start(); - expect(log.calledWith(INFO_LOG, 'Starting all Kibana monitoring collectors')).to.be(true); - - collector.cleanup(); - expect(log.calledWith(INFO_LOG, 'Stopping all Kibana monitoring collectors')).to.be(true); - - collector.start(); - expect(log.calledWith(INFO_LOG, 'Starting all Kibana monitoring collectors')).to.be(true); - - // exit - collector.cleanup(); - done(); - }); - }); -}); diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_logger.js b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_logger.js new file mode 100644 index 00000000000000..463b19a35bd0cb --- /dev/null +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_logger.js @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG } from '../../../common/constants'; + +const LOGGING_TAGS = [LOGGING_TAG, KIBANA_MONITORING_LOGGING_TAG]; + +/* + * @param {Object} server + * @return {Object} helpful logger object + */ +export function getCollectorLogger(server) { + return { + debug: message => server.log(['debug', ...LOGGING_TAGS], message), + info: message => server.log(['info', ...LOGGING_TAGS], message), + warn: message => server.log(['warning', ...LOGGING_TAGS], message) + }; +} diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_types_combiner.js b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_types_combiner.js index dfee99ca8d1d7f..f50b080a9afc9c 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_types_combiner.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/get_collector_types_combiner.js @@ -9,16 +9,28 @@ import { KIBANA_STATS_TYPE, KIBANA_SETTINGS_TYPE, KIBANA_USAGE_TYPE, - KIBANA_REPORTING_TYPE, } from '../../../common/constants'; +import { KIBANA_REPORTING_TYPE } from '../../../../reporting/common/constants'; import { sourceKibana } from './source_kibana'; /* - * Note: The ES Bulk Data Format is an array with 2 objects. - * The first object is the header, it has a field for the action (index), and - * metadata of the document (_index, _type, _id). - * Since the action types are always "index", there second object which is the - * payload, or the actual document to index. + * Combine stats collected from different sources into a single bulk payload. + * + * The ES Bulk Data Format is an array with 2 objects: + * - The first object is the header, it has a field for the action (index), and + * metadata of the document (_index, _type, _id). + * - The second object is the actual document to index. + * + * NOTE: https://github.com/elastic/kibana/issues/12504 asks that plugins have + * a way to register their own stats. It's not hard to move the stats collector + * methods under the ownership of the plugins that want it, but this module's + * behavior doesn't fit well with plugins registering their own stats. See the + * abstraction leak comments in the code. + * + * This module should go away when stats are collected by a Kibana metricbeat moduleset. + * - Individual plugin operational stats can be added to the `/stats?extended` API response. + * - Individual plugin usage stats can go into a new API similar to the `_xpack/usage` API in ES. + * - Each plugin will have its own top-level property in the responses for these APIs. */ export function getCollectorTypesCombiner(kbnServer, config, _sourceKibana = sourceKibana) { return payload => { @@ -37,7 +49,7 @@ export function getCollectorTypesCombiner(kbnServer, config, _sourceKibana = sou if (statsHeader && statsPayload) { const [ usageHeader, usagePayload ] = findItem(KIBANA_USAGE_TYPE); const kibanaUsage = (usageHeader && usagePayload) ? usagePayload : null; - const reportingUsage = (reportingHeader && reportingPayload) ? reportingPayload : null; + const reportingUsage = (reportingHeader && reportingPayload) ? reportingPayload : null; // this is an abstraction leak statsResult = [ statsHeader, { @@ -49,7 +61,7 @@ export function getCollectorTypesCombiner(kbnServer, config, _sourceKibana = sou set(statsResult, '[1].usage', kibanaUsage); } if (reportingUsage) { - set(statsResult, '[1].usage.xpack.reporting', reportingUsage); + set(statsResult, '[1].usage.xpack.reporting', reportingUsage); // this is an abstraction leak } } diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/lib/index.js b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/index.js new file mode 100644 index 00000000000000..d38fc8ede5604f --- /dev/null +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/lib/index.js @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { getCollectorLogger } from './get_collector_logger'; diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/start_collector.js b/x-pack/plugins/monitoring/server/kibana_monitoring/start_collector_set.js similarity index 71% rename from x-pack/plugins/monitoring/server/kibana_monitoring/start_collector.js rename to x-pack/plugins/monitoring/server/kibana_monitoring/start_collector_set.js index 0d7ee9ceec5091..434b3009aa07c0 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/start_collector.js +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/start_collector_set.js @@ -5,11 +5,10 @@ */ import { callClusterFactory } from '../../../xpack_main'; -import { TypeCollector } from './lib/type_collector'; +import { CollectorSet } from './classes/collector_set'; import { getOpsStatsCollector } from './collectors/get_ops_stats_collector'; import { getSettingsCollector } from './collectors/get_settings_collector'; -import { getUsageCollector } from './collectors/get_usage_collector'; -import { getReportingCollector } from './collectors/get_reporting_collector'; +import { getKibanaUsageCollector } from './collectors/get_kibana_usage_collector'; import { sendBulkPayload } from './lib/send_bulk_payload'; import { getCollectorTypesCombiner } from './lib/get_collector_types_combiner'; @@ -21,16 +20,14 @@ import { getCollectorTypesCombiner } from './lib/get_collector_types_combiner'; * @param kbnServer {Object} manager of Kibana services - see `src/server/kbn_server` in Kibana core * @param server {Object} HapiJS server instance * @param client {Object} Dedicated ES Client with monitoringBulk plugin + * @return {Object} CollectorSet instance */ -export function startCollector(kbnServer, server, client, _sendBulkPayload = sendBulkPayload) { +export function startCollectorSet(kbnServer, server, client, _sendBulkPayload = sendBulkPayload) { const config = server.config(); const interval = config.get('xpack.monitoring.kibana.collection.interval'); - const collector = new TypeCollector({ + const collectorSet = new CollectorSet(server, { interval, - logger(...message) { - server.log(...message); - }, combineTypes: getCollectorTypesCombiner(kbnServer, config), onPayload(payload) { return _sendBulkPayload(client, interval, payload); @@ -38,19 +35,20 @@ export function startCollector(kbnServer, server, client, _sendBulkPayload = sen }); const callCluster = callClusterFactory(server).getCallClusterInternal(); - collector.register(getUsageCollector(server, callCluster)); - collector.register(getOpsStatsCollector(server)); - collector.register(getSettingsCollector(server)); - collector.register(getReportingCollector(server, callCluster)); + collectorSet.register(getKibanaUsageCollector(server, callCluster)); + collectorSet.register(getOpsStatsCollector(server)); + collectorSet.register(getSettingsCollector(server)); // Startup Kibana cleanly or reconnect to Elasticsearch server.plugins.elasticsearch.status.on('green', () => { - collector.start(); + collectorSet.start(); }); // If connection to elasticsearch is lost // NOTE it is possible for the plugin status to go from red to red and trigger cleanup twice server.plugins.elasticsearch.status.on('red', () => { - collector.cleanup(); + collectorSet.cleanup(); }); + + return collectorSet; } diff --git a/x-pack/plugins/monitoring/server/lib/beats/get_beat_summary.js b/x-pack/plugins/monitoring/server/lib/beats/get_beat_summary.js index bc5d3a50d7a346..a585a234a0413a 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/get_beat_summary.js +++ b/x-pack/plugins/monitoring/server/lib/beats/get_beat_summary.js @@ -71,7 +71,7 @@ export async function getBeatSummary(req, beatsIndexPattern, { clusterUuid, beat query: createBeatsQuery({ start, end, - uuid: clusterUuid, + clusterUuid, filters }), collapse: { diff --git a/x-pack/plugins/monitoring/server/lib/beats/get_beats.js b/x-pack/plugins/monitoring/server/lib/beats/get_beats.js index 290c28ff4c178c..4d8019b94a287b 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/get_beats.js +++ b/x-pack/plugins/monitoring/server/lib/beats/get_beats.js @@ -114,7 +114,7 @@ export async function getBeats(req, beatsIndexPattern, clusterUuid) { query: createBeatsQuery({ start, end, - uuid: clusterUuid + clusterUuid }), collapse: { field: 'beats_stats.metrics.beat.info.ephemeral_id', // collapse on ephemeral_id to handle restarts diff --git a/x-pack/plugins/monitoring/server/lib/beats/get_beats_for_clusters.js b/x-pack/plugins/monitoring/server/lib/beats/get_beats_for_clusters.js index b35f538fe19d3d..ab9398184a95a8 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/get_beats_for_clusters.js +++ b/x-pack/plugins/monitoring/server/lib/beats/get_beats_for_clusters.js @@ -5,7 +5,8 @@ */ import { checkParam } from '../error_missing_required'; -import { createBeatsQuery } from './create_beats_query.js'; +import { BeatsClusterMetric } from '../metrics'; +import { createBeatsQuery } from './create_beats_query'; import { beatsAggFilterPath, beatsUuidsAgg, @@ -50,7 +51,8 @@ export function getBeatsForClusters(req, beatsIndexPattern, clusters) { query: createBeatsQuery({ start, end, - uuid: clusterUuid, + clusterUuid, + metric: BeatsClusterMetric.getMetricFields() // override default of BeatMetric.getMetricFields }), aggs: beatsUuidsAgg(maxBucketSize) } @@ -58,6 +60,6 @@ export function getBeatsForClusters(req, beatsIndexPattern, clusters) { const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring'); const response = await callWithRequest(req, 'search', params); - return handleResponse(clusterUuid, response, start, end); + return handleResponse(clusterUuid, response); })); } diff --git a/x-pack/plugins/monitoring/server/lib/beats/get_latest_stats.js b/x-pack/plugins/monitoring/server/lib/beats/get_latest_stats.js index 331ddcf1ee79b2..58f28cad334271 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/get_latest_stats.js +++ b/x-pack/plugins/monitoring/server/lib/beats/get_latest_stats.js @@ -83,7 +83,7 @@ export function getLatestStats(req, beatsIndexPattern, clusterUuid) { filterPath: 'aggregations', body: { query: createBeatsQuery({ - uuid: clusterUuid, + clusterUuid, filters: [ lastDayFilter ], }), aggs: { diff --git a/x-pack/plugins/monitoring/server/lib/beats/get_stats.js b/x-pack/plugins/monitoring/server/lib/beats/get_stats.js index 264886cefce56a..579fa4bd01837a 100644 --- a/x-pack/plugins/monitoring/server/lib/beats/get_stats.js +++ b/x-pack/plugins/monitoring/server/lib/beats/get_stats.js @@ -43,7 +43,7 @@ export async function getStats(req, beatsIndexPattern, clusterUuid) { query: createBeatsQuery({ start, end, - uuid: clusterUuid, + clusterUuid, }), aggs: beatsUuidsAgg(maxBucketSize) } diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__test__/__snapshots__/get_clusters_summary.test.js.snap b/x-pack/plugins/monitoring/server/lib/cluster/__test__/__snapshots__/get_clusters_summary.test.js.snap new file mode 100644 index 00000000000000..7a27dc22e1d412 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/cluster/__test__/__snapshots__/get_clusters_summary.test.js.snap @@ -0,0 +1,411 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`getClustersSummary should summarize cluster data with a primary cluster 1`] = ` +Array [ + Object { + "alerts": Object { + "alertsMeta": Object { + "enabled": true, + }, + }, + "beats": Object { + "beats": Object { + "total": null, + "types": Array [], + }, + "bytesSent": null, + "totalEvents": null, + }, + "cluster_name": "proddy1", + "cluster_uuid": "fOt6KT9KTICAMm2ncRhsMg", + "elasticsearch": Object { + "cluster_stats": Object { + "indices": Object { + "count": 1, + "docs": Object { + "count": 9, + "deleted": 0, + }, + "shards": Object { + "index": Object { + "primaries": Object { + "avg": 1, + "max": 1, + "min": 1, + }, + "replication": Object { + "avg": 0, + "max": 0, + "min": 0, + }, + "shards": Object { + "avg": 1, + "max": 1, + "min": 1, + }, + }, + "primaries": 1, + "replication": 0, + "total": 1, + }, + "store": Object { + "size_in_bytes": 37182, + }, + }, + "nodes": Object { + "count": Object { + "total": 1, + }, + "fs": Object { + "available_in_bytes": 224468717568, + "free_in_bytes": 228403855360, + "total_in_bytes": 499963170816, + }, + "jvm": Object { + "max_uptime_in_millis": 898395, + "mem": Object { + "heap_max_in_bytes": 731840512, + "heap_used_in_bytes": 273930776, + }, + }, + }, + "status": "green", + }, + }, + "isPrimary": true, + "isSupported": true, + "kibana": Object { + "concurrent_connections": 1, + "count": 1, + "memory_limit": 1501560832, + "memory_size": 208977920, + "requests_total": 1, + "response_time_max": 69, + "status": "green", + }, + "license": Object { + "expiry_date_in_millis": 1526499128764, + "status": "active", + "type": "trial", + }, + "logstash": Object { + "avg_memory": 0, + "avg_memory_used": 0, + "events_in_total": 0, + "events_out_total": 0, + "max_uptime": 0, + "node_count": 0, + "pipeline_count": 0, + "versions": Array [], + }, + "ml": undefined, + "status": "green", + "version": "7.0.0-alpha1", + }, + Object { + "alerts": Object { + "alertsMeta": Object { + "enabled": true, + }, + }, + "beats": Object { + "beats": Object { + "total": null, + "types": Array [], + }, + "bytesSent": null, + "totalEvents": null, + }, + "cluster_name": "monitoring-one", + "cluster_uuid": "F4hFnr5JQQayOzd8yG1rSg", + "elasticsearch": Object { + "cluster_stats": Object { + "indices": Object { + "count": 6, + "docs": Object { + "count": 557, + "deleted": 1, + }, + "shards": Object { + "index": Object { + "primaries": Object { + "avg": 1, + "max": 1, + "min": 1, + }, + "replication": Object { + "avg": 0, + "max": 0, + "min": 0, + }, + "shards": Object { + "avg": 1, + "max": 1, + "min": 1, + }, + }, + "primaries": 6, + "replication": 0, + "total": 6, + }, + "store": Object { + "size_in_bytes": 651556, + }, + }, + "nodes": Object { + "count": Object { + "total": 1, + }, + "fs": Object { + "available_in_bytes": 224468783104, + "free_in_bytes": 228403920896, + "total_in_bytes": 499963170816, + }, + "jvm": Object { + "max_uptime_in_millis": 922788, + "mem": Object { + "heap_max_in_bytes": 731840512, + "heap_used_in_bytes": 271001920, + }, + }, + }, + "status": "green", + }, + }, + "isPrimary": false, + "isSupported": true, + "kibana": Object { + "concurrent_connections": 0, + "count": 0, + "memory_limit": 0, + "memory_size": 0, + "requests_total": 0, + "response_time_max": 0, + "status": null, + }, + "license": Object { + "expiry_date_in_millis": 1526499102070, + "status": "active", + "type": "trial", + }, + "logstash": Object { + "avg_memory": 0, + "avg_memory_used": 0, + "events_in_total": 0, + "events_out_total": 0, + "max_uptime": 0, + "node_count": 0, + "pipeline_count": 0, + "versions": Array [], + }, + "ml": undefined, + "status": "green", + "version": "7.0.0-alpha1", + }, +] +`; + +exports[`getClustersSummary should summarize cluster data with no primary cluster 1`] = ` +Array [ + Object { + "alerts": Object { + "alertsMeta": Object { + "enabled": true, + }, + }, + "beats": Object { + "beats": Object { + "total": null, + "types": Array [], + }, + "bytesSent": null, + "totalEvents": null, + }, + "cluster_name": "proddy1", + "cluster_uuid": "fOt6KT9KTICAMm2ncRhsMg", + "elasticsearch": Object { + "cluster_stats": Object { + "indices": Object { + "count": 1, + "docs": Object { + "count": 9, + "deleted": 0, + }, + "shards": Object { + "index": Object { + "primaries": Object { + "avg": 1, + "max": 1, + "min": 1, + }, + "replication": Object { + "avg": 0, + "max": 0, + "min": 0, + }, + "shards": Object { + "avg": 1, + "max": 1, + "min": 1, + }, + }, + "primaries": 1, + "replication": 0, + "total": 1, + }, + "store": Object { + "size_in_bytes": 37182, + }, + }, + "nodes": Object { + "count": Object { + "total": 1, + }, + "fs": Object { + "available_in_bytes": 224468717568, + "free_in_bytes": 228403855360, + "total_in_bytes": 499963170816, + }, + "jvm": Object { + "max_uptime_in_millis": 898395, + "mem": Object { + "heap_max_in_bytes": 731840512, + "heap_used_in_bytes": 273930776, + }, + }, + }, + "status": "green", + }, + }, + "isPrimary": false, + "isSupported": true, + "kibana": Object { + "concurrent_connections": 1, + "count": 1, + "memory_limit": 1501560832, + "memory_size": 208977920, + "requests_total": 1, + "response_time_max": 69, + "status": "green", + }, + "license": Object { + "expiry_date_in_millis": 1526499128764, + "status": "active", + "type": "trial", + }, + "logstash": Object { + "avg_memory": 0, + "avg_memory_used": 0, + "events_in_total": 0, + "events_out_total": 0, + "max_uptime": 0, + "node_count": 0, + "pipeline_count": 0, + "versions": Array [], + }, + "ml": undefined, + "status": "green", + "version": "7.0.0-alpha1", + }, + Object { + "alerts": Object { + "alertsMeta": Object { + "enabled": true, + }, + }, + "beats": Object { + "beats": Object { + "total": null, + "types": Array [], + }, + "bytesSent": null, + "totalEvents": null, + }, + "cluster_name": "monitoring-one", + "cluster_uuid": "F4hFnr5JQQayOzd8yG1rSg", + "elasticsearch": Object { + "cluster_stats": Object { + "indices": Object { + "count": 6, + "docs": Object { + "count": 557, + "deleted": 1, + }, + "shards": Object { + "index": Object { + "primaries": Object { + "avg": 1, + "max": 1, + "min": 1, + }, + "replication": Object { + "avg": 0, + "max": 0, + "min": 0, + }, + "shards": Object { + "avg": 1, + "max": 1, + "min": 1, + }, + }, + "primaries": 6, + "replication": 0, + "total": 6, + }, + "store": Object { + "size_in_bytes": 651556, + }, + }, + "nodes": Object { + "count": Object { + "total": 1, + }, + "fs": Object { + "available_in_bytes": 224468783104, + "free_in_bytes": 228403920896, + "total_in_bytes": 499963170816, + }, + "jvm": Object { + "max_uptime_in_millis": 922788, + "mem": Object { + "heap_max_in_bytes": 731840512, + "heap_used_in_bytes": 271001920, + }, + }, + }, + "status": "green", + }, + }, + "isPrimary": false, + "isSupported": true, + "kibana": Object { + "concurrent_connections": 0, + "count": 0, + "memory_limit": 0, + "memory_size": 0, + "requests_total": 0, + "response_time_max": 0, + "status": null, + }, + "license": Object { + "expiry_date_in_millis": 1526499102070, + "status": "active", + "type": "trial", + }, + "logstash": Object { + "avg_memory": 0, + "avg_memory_used": 0, + "events_in_total": 0, + "events_out_total": 0, + "max_uptime": 0, + "node_count": 0, + "pipeline_count": 0, + "versions": Array [], + }, + "ml": undefined, + "status": "green", + "version": "7.0.0-alpha1", + }, +] +`; diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__test__/fixtures/clusters.json b/x-pack/plugins/monitoring/server/lib/cluster/__test__/fixtures/clusters.json new file mode 100644 index 00000000000000..a2b89b7c92dd2f --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/cluster/__test__/fixtures/clusters.json @@ -0,0 +1,682 @@ +[ + { + "cluster_uuid": "fOt6KT9KTICAMm2ncRhsMg", + "cluster_name": "proddy1", + "version": "7.0.0-alpha1", + "license": { + "status": "active", + "uid": "09f3fb66-6d77-4223-ab4e-c5a7ee7b1585", + "type": "trial", + "issue_date": "2018-04-16T19:32:08.764Z", + "issue_date_in_millis": 1523907128764, + "expiry_date": "2018-05-16T19:32:08.764Z", + "expiry_date_in_millis": 1526499128764, + "max_nodes": 1000, + "issued_to": "proddy1", + "issuer": "elasticsearch", + "start_date_in_millis": -1 + }, + "cluster_stats": { + "timestamp": 1523908015525, + "status": "green", + "indices": { + "count": 1, + "shards": { + "total": 1, + "primaries": 1, + "replication": 0, + "index": { + "shards": { + "min": 1, + "max": 1, + "avg": 1 + }, + "primaries": { + "min": 1, + "max": 1, + "avg": 1 + }, + "replication": { + "min": 0, + "max": 0, + "avg": 0 + } + } + }, + "docs": { + "count": 9, + "deleted": 0 + }, + "store": { + "size_in_bytes": 37182 + }, + "fielddata": { + "memory_size_in_bytes": 0, + "evictions": 0 + }, + "query_cache": { + "memory_size_in_bytes": 0, + "total_count": 0, + "hit_count": 0, + "miss_count": 0, + "cache_size": 0, + "cache_count": 0, + "evictions": 0 + }, + "completion": { + "size_in_bytes": 0 + }, + "segments": { + "count": 9, + "memory_in_bytes": 14272, + "terms_memory_in_bytes": 10251, + "stored_fields_memory_in_bytes": 2808, + "term_vectors_memory_in_bytes": 0, + "norms_memory_in_bytes": 320, + "points_memory_in_bytes": 9, + "doc_values_memory_in_bytes": 884, + "index_writer_memory_in_bytes": 0, + "version_map_memory_in_bytes": 0, + "fixed_bit_set_memory_in_bytes": 0, + "max_unsafe_auto_id_timestamp": -1, + "file_sizes": {} + } + }, + "nodes": { + "count": { + "total": 1, + "data": 1, + "coordinating_only": 0, + "master": 1, + "ingest": 1 + }, + "versions": [ + "7.0.0-alpha1" + ], + "os": { + "available_processors": 8, + "allocated_processors": 1, + "names": [ + { + "name": "Mac OS X", + "count": 1 + } + ], + "mem": { + "total_in_bytes": 17179869184, + "free_in_bytes": 357588992, + "used_in_bytes": 16822280192, + "free_percent": 2, + "used_percent": 98 + } + }, + "process": { + "cpu": { + "percent": 0 + }, + "open_file_descriptors": { + "min": 212, + "max": 212, + "avg": 212 + } + }, + "jvm": { + "max_uptime_in_millis": 898395, + "versions": [ + { + "version": "10", + "vm_name": "Java HotSpot(TM) 64-Bit Server VM", + "vm_version": "10+46", + "vm_vendor": "\"Oracle Corporation\"", + "count": 1 + } + ], + "mem": { + "heap_used_in_bytes": 273930776, + "heap_max_in_bytes": 731840512 + }, + "threads": 43 + }, + "fs": { + "total_in_bytes": 499963170816, + "free_in_bytes": 228403855360, + "available_in_bytes": 224468717568 + }, + "plugins": [ + { + "name": "x-pack-upgrade", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Upgrade", + "classname": "org.elasticsearch.xpack.upgrade.Upgrade", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-sql", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "The Elasticsearch plugin that powers SQL for Elasticsearch", + "classname": "org.elasticsearch.xpack.sql.plugin.SqlPlugin", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-ml", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Machine Learning", + "classname": "org.elasticsearch.xpack.ml.MachineLearning", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": true + }, + { + "name": "x-pack-logstash", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Logstash", + "classname": "org.elasticsearch.xpack.logstash.Logstash", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-deprecation", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Deprecation", + "classname": "org.elasticsearch.xpack.deprecation.Deprecation", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-monitoring", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Monitoring", + "classname": "org.elasticsearch.xpack.monitoring.Monitoring", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-core", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Core", + "classname": "org.elasticsearch.xpack.core.XPackPlugin", + "extended_plugins": [], + "has_native_controller": false + }, + { + "name": "x-pack-security", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Security", + "classname": "org.elasticsearch.xpack.security.Security", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-rollup", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Rollup", + "classname": "org.elasticsearch.xpack.rollup.Rollup", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-watcher", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Watcher", + "classname": "org.elasticsearch.xpack.watcher.Watcher", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-graph", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Graph", + "classname": "org.elasticsearch.xpack.graph.Graph", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + } + ], + "network_types": { + "transport_types": { + "security4": 1 + }, + "http_types": { + "security4": 1 + } + } + } + }, + "cluster_state": { + "nodes_hash": -1775623708, + "status": "green", + "version": 10, + "state_uuid": "24ATwSkUS2Ky-hcR-uPRhA", + "master_node": "lLDq_ptaTRm6ntW7KPAmkQ", + "nodes": { + "lLDq_ptaTRm6ntW7KPAmkQ": { + "name": "nodey01", + "ephemeral_id": "P-xGmWktSCWsG4PcbEGcMg", + "transport_address": "127.0.0.1:9301", + "attributes": { + "ml.machine_memory": "17179869184", + "ml.max_open_jobs": "20", + "ml.enabled": "true" + } + } + } + }, + "isSupported": true, + "alerts": { + "alertsMeta": { + "enabled": true + } + }, + "kibana": { + "uuids": [ + "46205c28-9d41-447a-a438-c8b86fb5d1ce" + ], + "status": "green", + "requests_total": 1, + "concurrent_connections": 1, + "response_time_max": 69, + "memory_size": 208977920, + "memory_limit": 1501560832, + "count": 1 + }, + "logstash": { + "node_count": 0, + "events_in_total": 0, + "events_out_total": 0, + "avg_memory": 0, + "avg_memory_used": 0, + "max_uptime": 0, + "pipeline_count": 0, + "versions": [] + }, + "beats": { + "totalEvents": null, + "bytesSent": null, + "beats": { + "total": null, + "types": [] + } + } + }, + { + "cluster_uuid": "F4hFnr5JQQayOzd8yG1rSg", + "cluster_name": "monitoring-one", + "version": "7.0.0-alpha1", + "license": { + "status": "active", + "uid": "5d32fcdb-3f3b-4816-a8a9-8bac1c2a73a6", + "type": "trial", + "issue_date": "2018-04-16T19:31:42.070Z", + "issue_date_in_millis": 1523907102070, + "expiry_date": "2018-05-16T19:31:42.070Z", + "expiry_date_in_millis": 1526499102070, + "max_nodes": 1000, + "issued_to": "monitoring-one", + "issuer": "elasticsearch", + "start_date_in_millis": -1 + }, + "cluster_stats": { + "timestamp": 1523908013287, + "status": "green", + "indices": { + "count": 6, + "shards": { + "total": 6, + "primaries": 6, + "replication": 0, + "index": { + "shards": { + "min": 1, + "max": 1, + "avg": 1 + }, + "primaries": { + "min": 1, + "max": 1, + "avg": 1 + }, + "replication": { + "min": 0, + "max": 0, + "avg": 0 + } + } + }, + "docs": { + "count": 557, + "deleted": 1 + }, + "store": { + "size_in_bytes": 651556 + }, + "fielddata": { + "memory_size_in_bytes": 848, + "evictions": 0 + }, + "query_cache": { + "memory_size_in_bytes": 0, + "total_count": 0, + "hit_count": 0, + "miss_count": 0, + "cache_size": 0, + "cache_count": 0, + "evictions": 0 + }, + "completion": { + "size_in_bytes": 0 + }, + "segments": { + "count": 27, + "memory_in_bytes": 120198, + "terms_memory_in_bytes": 85510, + "stored_fields_memory_in_bytes": 8480, + "term_vectors_memory_in_bytes": 0, + "norms_memory_in_bytes": 4928, + "points_memory_in_bytes": 1020, + "doc_values_memory_in_bytes": 20260, + "index_writer_memory_in_bytes": 174805, + "version_map_memory_in_bytes": 16836, + "fixed_bit_set_memory_in_bytes": 104, + "max_unsafe_auto_id_timestamp": -1, + "file_sizes": {} + } + }, + "nodes": { + "count": { + "total": 1, + "data": 1, + "coordinating_only": 0, + "master": 1, + "ingest": 1 + }, + "versions": [ + "7.0.0-alpha1" + ], + "os": { + "available_processors": 8, + "allocated_processors": 1, + "names": [ + { + "name": "Mac OS X", + "count": 1 + } + ], + "mem": { + "total_in_bytes": 17179869184, + "free_in_bytes": 359727104, + "used_in_bytes": 16820142080, + "free_percent": 2, + "used_percent": 98 + } + }, + "process": { + "cpu": { + "percent": 2 + }, + "open_file_descriptors": { + "min": 204, + "max": 204, + "avg": 204 + } + }, + "jvm": { + "max_uptime_in_millis": 922788, + "versions": [ + { + "version": "10", + "vm_name": "Java HotSpot(TM) 64-Bit Server VM", + "vm_version": "10+46", + "vm_vendor": "\"Oracle Corporation\"", + "count": 1 + } + ], + "mem": { + "heap_used_in_bytes": 271001920, + "heap_max_in_bytes": 731840512 + }, + "threads": 39 + }, + "fs": { + "total_in_bytes": 499963170816, + "free_in_bytes": 228403920896, + "available_in_bytes": 224468783104 + }, + "plugins": [ + { + "name": "x-pack-upgrade", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Upgrade", + "classname": "org.elasticsearch.xpack.upgrade.Upgrade", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-sql", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "The Elasticsearch plugin that powers SQL for Elasticsearch", + "classname": "org.elasticsearch.xpack.sql.plugin.SqlPlugin", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-ml", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Machine Learning", + "classname": "org.elasticsearch.xpack.ml.MachineLearning", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": true + }, + { + "name": "x-pack-logstash", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Logstash", + "classname": "org.elasticsearch.xpack.logstash.Logstash", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-deprecation", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Deprecation", + "classname": "org.elasticsearch.xpack.deprecation.Deprecation", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-monitoring", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Monitoring", + "classname": "org.elasticsearch.xpack.monitoring.Monitoring", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-core", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Core", + "classname": "org.elasticsearch.xpack.core.XPackPlugin", + "extended_plugins": [], + "has_native_controller": false + }, + { + "name": "x-pack-security", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Security", + "classname": "org.elasticsearch.xpack.security.Security", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-rollup", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Rollup", + "classname": "org.elasticsearch.xpack.rollup.Rollup", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-watcher", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Watcher", + "classname": "org.elasticsearch.xpack.watcher.Watcher", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + }, + { + "name": "x-pack-graph", + "version": "7.0.0-alpha1", + "elasticsearch_version": "7.0.0-alpha1", + "java_version": "1.8", + "description": "Elasticsearch Expanded Pack Plugin - Graph", + "classname": "org.elasticsearch.xpack.graph.Graph", + "extended_plugins": [ + "x-pack-core" + ], + "has_native_controller": false + } + ], + "network_types": { + "transport_types": { + "security4": 1 + }, + "http_types": { + "security4": 1 + } + } + } + }, + "cluster_state": { + "nodes_hash": -721035764, + "status": "green", + "version": 37, + "state_uuid": "FE17aYiRRHSxPqolSADJyw", + "master_node": "iPcqcwhiRv-RDQjYSaXrkg", + "nodes": { + "iPcqcwhiRv-RDQjYSaXrkg": { + "name": "monitoring-one-01", + "ephemeral_id": "46J0NLewQQCza8de7CnFvw", + "transport_address": "127.0.0.1:9300", + "attributes": { + "ml.machine_memory": "17179869184", + "ml.max_open_jobs": "20", + "ml.enabled": "true" + } + } + } + }, + "isSupported": true, + "alerts": { + "alertsMeta": { + "enabled": true + } + }, + "kibana": { + "uuids": [], + "status": null, + "requests_total": 0, + "concurrent_connections": 0, + "response_time_max": 0, + "memory_size": 0, + "memory_limit": 0, + "count": 0 + }, + "logstash": { + "node_count": 0, + "events_in_total": 0, + "events_out_total": 0, + "avg_memory": 0, + "avg_memory_used": 0, + "max_uptime": 0, + "pipeline_count": 0, + "versions": [] + }, + "beats": { + "totalEvents": null, + "bytesSent": null, + "beats": { + "total": null, + "types": [] + } + } + } +] diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__test__/get_clusters_summary.test.js b/x-pack/plugins/monitoring/server/lib/cluster/__test__/get_clusters_summary.test.js new file mode 100644 index 00000000000000..c1725b91473429 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/cluster/__test__/get_clusters_summary.test.js @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import clusters from './fixtures/clusters'; +import { getClustersSummary } from '../get_clusters_summary'; + +describe('getClustersSummary', () => { + it('should summarize cluster data with a primary cluster', () => { + const kibanaUuid = '46205c28-9d41-447a-a438-c8b86fb5d1ce'; + const result = getClustersSummary(clusters, kibanaUuid); + expect(result).toMatchSnapshot(); + }); + + it('should summarize cluster data with no primary cluster', () => { + const kibanaUuid = null; + const result = getClustersSummary(clusters, kibanaUuid); + expect(result).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js index b897a79a767516..427cd5af19ab11 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js +++ b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_from_request.js @@ -13,35 +13,12 @@ import { getKibanasForClusters } from '../kibana'; import { getLogstashForClusters } from '../logstash'; import { getPipelines } from '../logstash/get_pipelines'; import { getBeatsForClusters } from '../beats'; -import { calculateOverallStatus } from '../calculate_overall_status'; import { alertsClustersAggregation } from '../../cluster_alerts/alerts_clusters_aggregation'; import { alertsClusterSearch } from '../../cluster_alerts/alerts_cluster_search'; import { checkLicense as checkLicenseForAlerts } from '../../cluster_alerts/check_license'; +import { getClustersSummary } from './get_clusters_summary'; import { CLUSTER_ALERTS_SEARCH_SIZE } from '../../../common/constants'; -// manipulate cluster status and license meta data -export function normalizeClustersData(clusters, kibanaUuid) { - clusters.forEach(cluster => { - cluster.elasticsearch = { - cluster_stats: cluster.cluster_stats, - nodes: cluster.nodes, - indices: cluster.indices - }; - cluster.status = calculateOverallStatus([ - cluster.elasticsearch.status, - cluster.kibana && cluster.kibana.status || null - ]); - cluster.isPrimary = cluster.kibana.uuids.includes(kibanaUuid); - - delete cluster.cluster_stats; - delete cluster.nodes; - delete cluster.indices; - delete cluster.kibana.uuids; - }); - - return clusters; -} - /** * Get all clusters or the cluster associated with {@code clusterUuid} when it is defined. */ @@ -131,5 +108,5 @@ export async function getClustersFromRequest(req, indexPatterns, { clusterUuid, const config = req.server.config(); const kibanaUuid = config.get('server.uuid'); - return normalizeClustersData(clusters, kibanaUuid); + return getClustersSummary(clusters, kibanaUuid); } diff --git a/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_summary.js b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_summary.js new file mode 100644 index 00000000000000..3dc19e70c88918 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/cluster/get_clusters_summary.js @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { pick, omit } from 'lodash'; +import { calculateOverallStatus } from '../calculate_overall_status'; + +export function getClustersSummary(clusters, kibanaUuid) { + return clusters.map(cluster => { + const { + isSupported, + cluster_uuid: clusterUuid, + cluster_name: clusterName, + version, + license, + cluster_stats: clusterStats, + logstash, + kibana, + ml, + beats, + alerts + } = cluster; + + const { + status: licenseStatus, + type: licenseType, + expiry_date_in_millis: licenseExpiry + } = license; + + const indices = pick(clusterStats.indices, ['count', 'docs', 'shards', 'store']); + + const jvm = { + max_uptime_in_millis: clusterStats.nodes.jvm.max_uptime_in_millis, + mem: clusterStats.nodes.jvm.mem + }; + + const nodes = { + fs: clusterStats.nodes.fs, + count: { + total: clusterStats.nodes.count.total + }, + jvm + }; + const { status } = cluster.cluster_state; + + return { + isSupported, + cluster_uuid: clusterUuid, + cluster_name: clusterName, + version, + license: { + status: licenseStatus, + type: licenseType, + expiry_date_in_millis: licenseExpiry + }, + elasticsearch: { + cluster_stats: { + indices, + nodes, + status + } + }, + logstash, + kibana: omit(kibana, 'uuids'), + ml, + beats, + alerts, + isPrimary: kibana.uuids.includes(kibanaUuid), + status: calculateOverallStatus([ + status, + kibana && kibana.status || null + ]) + }; + }); +} diff --git a/x-pack/plugins/monitoring/server/lib/details/get_series.js b/x-pack/plugins/monitoring/server/lib/details/get_series.js index 092eeced0f35aa..31ffe1e761688c 100644 --- a/x-pack/plugins/monitoring/server/lib/details/get_series.js +++ b/x-pack/plugins/monitoring/server/lib/details/get_series.js @@ -7,7 +7,7 @@ import { get } from 'lodash'; import moment from 'moment'; import { checkParam } from '../error_missing_required'; -import { metrics, serializeMetric } from '../metrics'; +import { metrics } from '../metrics'; import { createQuery } from '../create_query.js'; import { formatTimestampToDuration } from '../../../common'; import { @@ -196,7 +196,7 @@ function handleSeries(metric, min, max, bucketSizeInSeconds, response) { return { bucket_size: formatBucketSize(bucketSizeInSeconds), timeRange: { min, max }, - metric: serializeMetric(metric), + metric: metric.serialize(), data }; } diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/get_last_recovery.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/get_last_recovery.js index 71ff4ad90ef7d7..e73c0db63d8ea5 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/get_last_recovery.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/get_last_recovery.js @@ -6,7 +6,7 @@ import _ from 'lodash'; import { checkParam } from '../error_missing_required'; -import { createQuery } from '../create_query.js'; +import { createQuery } from '../create_query'; import { ElasticsearchMetric } from '../metrics'; /** diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/get_ml_jobs.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/get_ml_jobs.js index 9e1a83d95e3781..fbcd7c8f5a60e1 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/get_ml_jobs.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/get_ml_jobs.js @@ -7,7 +7,7 @@ import Promise from 'bluebird'; import { contains, get } from 'lodash'; import { checkParam } from '../error_missing_required'; -import { createQuery } from '../create_query.js'; +import { createQuery } from '../create_query'; import { ElasticsearchMetric } from '../metrics'; import { ML_SUPPORTED_LICENSES } from '../../../common/constants'; diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js index e2a0f5d877de82..fbe84b9e3d09af 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/__tests__/get_indices.js @@ -13,7 +13,7 @@ describe('Get Elasticsearch Indices', () => { expect(result).to.eql([]); }); - it('handle a simple response', () => { + it('should handle a simple response', () => { const resp = { hits: { hits: [{ @@ -30,12 +30,15 @@ describe('Get Elasticsearch Indices', () => { doc_count: undefined, data_size: undefined, index_rate: null, - search_rate: null + search_rate: null, + status: 'Deleted / Closed', + status_sort: 0, + unassigned_shards: undefined } ]); }); - it('handle a typical multi-hit response', () => { + it('should handle a multi-hit response with deleted/closed indices', () => { const resp = { 'hits': { 'hits': [ { @@ -97,14 +100,126 @@ describe('Get Elasticsearch Indices', () => { doc_count: 381, data_size: 3199059, index_rate: 0, - search_rate: 0 + search_rate: 0, + status: 'Deleted / Closed', + status_sort: 0, + unassigned_shards: undefined }, { name: 'cat-tweets-2017.08.08', doc_count: 31375, data_size: 239591867, index_rate: 13.30026455026455, - search_rate: 28.902116402116405 + search_rate: 28.902116402116405, + status: 'Deleted / Closed', + status_sort: 0, + unassigned_shards: undefined + } + ]); + }); + + it('should handle a multi-hit response with open indices', () => { + const resp = { + hits: { + hits: [ + { + _source: { + index_stats: { + index: 'avocado-tweets-2017.08.08', + primaries: { + docs: { count: 381 }, + indexing: { index_total: 15 } + }, + total: { + search: { query_total: 19345 }, + store: { size_in_bytes: 3199059 } + } + }, + timestamp: '2017-08-08T19:16:20.104Z' + }, + inner_hits: { + earliest: { + hits: { + hits: [ + { + _source: { + index_stats: { + primaries: { indexing: { index_total: 15 } }, + total: { search: { query_total: 19345 } } + }, + timestamp: '2017-08-08T18:16:28.898Z' + } + } + ] + } + } + } + }, + { + _source: { + index_stats: { + index: 'cat-tweets-2017.08.08', + primaries: { + docs: { count: 31375 }, + indexing: { index_total: 31377 } + }, + total: { + search: { query_total: 43155 }, + store: { size_in_bytes: 239591867 } + } + }, + timestamp: '2017-08-08T19:16:20.104Z' + }, + inner_hits: { + earliest: { + hits: { + hits: [ + { + _source: { + index_stats: { + primaries: { indexing: { index_total: 23333 } }, + total: { search: { query_total: 25675 } } + }, + timestamp: '2017-08-08T18:16:28.898Z' + } + } + ] + } + } + } + } + ] + } + }; + + const shardStats = { + indices: { + 'avocado-tweets-2017.08.08': { status: 'green', primary: 5, replica: 5, unassigned: { primary: 0, replica: 0 } }, + 'cat-tweets-2017.08.08': { status: 'yellow', primary: 5, replica: 5, unassigned: { primary: 0, replica: 1 } } + } + }; + + const result = handleResponse(resp, 0, 604800, shardStats); + expect(result).to.eql([ + { + name: 'avocado-tweets-2017.08.08', + doc_count: 381, + data_size: 3199059, + index_rate: 0, + search_rate: 0, + status: 'green', + status_sort: 1, + unassigned_shards: 0 + }, + { + name: 'cat-tweets-2017.08.08', + doc_count: 31375, + data_size: 239591867, + index_rate: 13.30026455026455, + search_rate: 28.902116402116405, + status: 'yellow', + status_sort: 2, + unassigned_shards: 1 } ]); }); diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_index_summary.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_index_summary.js index cbf6d05141db58..5417a33053ebc6 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_index_summary.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_index_summary.js @@ -6,7 +6,7 @@ import { get } from 'lodash'; import { checkParam } from '../../error_missing_required'; -import { createQuery } from '../../create_query.js'; +import { createQuery } from '../../create_query'; import { ElasticsearchMetric } from '../../metrics'; export function handleResponse(shardStats, indexUuid) { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_indices.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_indices.js index ef72e16cd6845f..1c8618fdd70141 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_indices.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/indices/get_indices.js @@ -9,8 +9,9 @@ import { checkParam } from '../../error_missing_required'; import { ElasticsearchMetric } from '../../metrics'; import { createQuery } from '../../create_query'; import { calculateRate } from '../../calculate_rate'; +import { getUnassignedShards } from '../shards'; -export function handleResponse(resp, min, max) { +export function handleResponse(resp, min, max, shardStats) { // map the hits const hits = get(resp, 'hits.hits', []); return hits.map(hit => { @@ -38,17 +39,42 @@ export function handleResponse(resp, min, max) { ...rateOptions }); + const shardStatsForIndex = get(shardStats, ['indices', stats.index]); + + let status; + let statusSort; + let unassignedShards; + if (shardStatsForIndex && shardStatsForIndex.status) { + status = shardStatsForIndex.status; + unassignedShards = getUnassignedShards(shardStatsForIndex); + + // create a numerical status value for sorting + if (status === 'green') { + statusSort = 1; + } else if (status === 'yellow') { + statusSort = 2; + } else { + statusSort = 3; + } + } else { + status = 'Deleted / Closed'; + statusSort = 0; + } + return { name: stats.index, + status, doc_count: get(stats, 'primaries.docs.count'), data_size: get(stats, 'total.store.size_in_bytes'), index_rate: indexRate, - search_rate: searchRate + search_rate: searchRate, + unassigned_shards: unassignedShards, + status_sort: statusSort }; }); } -export function getIndices(req, esIndexPattern, showSystemIndices = false) { +export function getIndices(req, esIndexPattern, showSystemIndices = false, shardStats) { checkParam(esIndexPattern, 'esIndexPattern in elasticsearch/getIndices'); const { min, max } = req.payload.timeRange; @@ -110,5 +136,5 @@ export function getIndices(req, esIndexPattern, showSystemIndices = false) { const { callWithRequest } = req.server.plugins.elasticsearch.getCluster('monitoring'); return callWithRequest(req, 'search', params) - .then(resp => handleResponse(resp, min, max)); + .then(resp => handleResponse(resp, min, max, shardStats)); } diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js index 2fc3bbf9d8ba0f..22e41a02eef867 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/__tests__/get_node_summary.js @@ -7,8 +7,8 @@ import expect from 'expect.js'; import { handleResponse } from '../get_node_summary'; -describe('get_node_summary handleResponse', () => { - it('default undefined fields in result for empty response', () => { +describe('Elasticsearch Node Summary get_node_summary handleResponse', () => { + it('should return undefined fields in result for empty response', () => { const clusterState = {}; const shardStats = {}; const resolver = null; @@ -24,13 +24,14 @@ describe('get_node_summary handleResponse', () => { nodeTypeLabel: 'Offline Node', node_ids: [], status: 'Offline', + isOnline: false, transport_address: '', type: 'node', }); }); describe('With node_stats hits', () => { - it('incomplete shardStats data', () => { + it('should handle incomplete shardStats data', () => { const clusterState = { nodes: { fooNode: {} @@ -63,10 +64,11 @@ describe('get_node_summary handleResponse', () => { nodeTypeClass: 'fa-server', node_ids: [], status: 'Online', + isOnline: true, }); }); - it('incomplete shardStats data, master node', () => { + it('should handle incomplete shardStats data, master node', () => { const clusterState = { nodes: { 'fooNode-Uuid': {} @@ -140,6 +142,7 @@ describe('get_node_summary handleResponse', () => { 'fooNode-Uuid' ], status: 'Online', + isOnline: true, }); }); }); diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_node_summary.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_node_summary.js index 42dcd577803e8f..bbe9c78ea7d6d1 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_node_summary.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_node_summary.js @@ -6,9 +6,8 @@ import { get } from 'lodash'; import { checkParam } from '../../error_missing_required'; -import { createQuery } from '../../create_query.js'; +import { createQuery } from '../../create_query'; import { ElasticsearchMetric } from '../../metrics'; - import { getDefaultNodeFromId } from './get_default_node_from_id'; import { calculateNodeType } from './calculate_node_type'; import { getNodeTypeClassLabel } from './get_node_type_class_label'; @@ -46,9 +45,14 @@ export function handleResponse(clusterState, shardStats, resolver) { freeSpace: get(sourceStats, 'fs.total.available_in_bytes'), usedHeap: get(sourceStats, 'jvm.mem.heap_used_percent'), status: 'Online', + isOnline: true, }; } else { - nodeSummary = { nodeTypeLabel: 'Offline Node', status: 'Offline', }; + nodeSummary = { + nodeTypeLabel: 'Offline Node', + status: 'Offline', + isOnline: false, + }; } return { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/get_nodes.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/get_nodes.js index 6271bcde03dd70..0eaaa7d0020503 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/get_nodes.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/get_nodes.js @@ -6,7 +6,7 @@ import moment from 'moment'; import { checkParam } from '../../../error_missing_required'; -import { createQuery } from '../../../create_query.js'; +import { createQuery } from '../../../create_query'; import { calculateAuto } from '../../../calculate_auto'; import { ElasticsearchMetric } from '../../../metrics'; import { getMetricAggs } from './get_metric_aggs'; diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/map_nodes_metrics.js b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/map_nodes_metrics.js index 1cfe9558960dc1..c29294e0536bbd 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/map_nodes_metrics.js +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/map_nodes_metrics.js @@ -6,7 +6,7 @@ import { get, pluck, min, max, last } from 'lodash'; import { filterPartialBuckets } from '../../../filter_partial_buckets'; -import { metrics, serializeMetric } from '../../../metrics'; +import { metrics } from '../../../metrics'; function calcSlope(data) { const length = data.length; @@ -85,7 +85,7 @@ function reduceMetric(metricName, metricBuckets, { min: startTime, max: endTime, const slope = calcSlope(mappedData) > 0 ? 1 : -1; // no need for the entire precison, it's just an up/down arrow return { - metric: serializeMetric(metric), + metric: metric.serialize(), summary: { minVal, maxVal, lastVal, slope } }; } diff --git a/x-pack/plugins/monitoring/server/lib/kibana/get_kibanas.js b/x-pack/plugins/monitoring/server/lib/kibana/get_kibanas.js index f7ad50dd6dc50f..edb600d2059c56 100644 --- a/x-pack/plugins/monitoring/server/lib/kibana/get_kibanas.js +++ b/x-pack/plugins/monitoring/server/lib/kibana/get_kibanas.js @@ -9,7 +9,7 @@ import moment from 'moment'; import { checkParam } from '../error_missing_required'; import { createQuery } from '../create_query'; import { calculateAvailability } from '../calculate_availability'; -import { ElasticsearchMetric } from '../metrics'; +import { KibanaMetric } from '../metrics'; /* * Get detailed info for Kibanas in the cluster @@ -39,7 +39,7 @@ export function getKibanas(req, kbnIndexPattern, { clusterUuid }) { start, end, clusterUuid, - metric: ElasticsearchMetric.getMetricFields() + metric: KibanaMetric.getMetricFields() }), collapse: { field: 'kibana_stats.kibana.uuid' diff --git a/x-pack/plugins/monitoring/server/lib/kibana/get_kibanas_for_clusters.js b/x-pack/plugins/monitoring/server/lib/kibana/get_kibanas_for_clusters.js index cd936fc54eeeae..34ec218ad5eb12 100644 --- a/x-pack/plugins/monitoring/server/lib/kibana/get_kibanas_for_clusters.js +++ b/x-pack/plugins/monitoring/server/lib/kibana/get_kibanas_for_clusters.js @@ -8,7 +8,7 @@ import Promise from 'bluebird'; import { chain, find, get } from 'lodash'; import { checkParam } from '../error_missing_required'; import { createQuery } from '../create_query.js'; -import { ElasticsearchMetric } from '../metrics'; +import { KibanaClusterMetric } from '../metrics'; /* * Get high-level info for Kibanas in a set of clusters @@ -32,7 +32,7 @@ export function getKibanasForClusters(req, kbnIndexPattern, clusters) { return Promise.map(clusters, cluster => { const clusterUuid = cluster.cluster_uuid; - const metric = ElasticsearchMetric.getMetricFields(); + const metric = KibanaClusterMetric.getMetricFields(); const params = { index: kbnIndexPattern, size: 0, diff --git a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js index 2277bb12814ab9..e2be73d10df805 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/__tests__/get_pipeline.js @@ -15,7 +15,7 @@ describe('get_pipeline', () => { let vertex; let vertexStatsBucket; let totalProcessorsDurationInMillis; - let timeboundsInMillis; + let timeseriesIntervalInSeconds; beforeEach(() => { vertex = { @@ -31,16 +31,16 @@ describe('get_pipeline', () => { }; totalProcessorsDurationInMillis = 24000; - timeboundsInMillis = 15 * 60 * 1000; + timeseriesIntervalInSeconds = 15 * 60; }); it('returns correct stats', () => { - const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeboundsInMillis); + const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds); expect(result).to.eql({ events_in: 10000, events_out: 9000, duration_in_millis: 18000, - events_per_millisecond: 0.00001, + events_out_per_millisecond: 0.01, millis_per_event: 2, queue_push_duration_in_millis: 100000, queue_push_duration_in_millis_per_event: 11.11111111111111 @@ -55,12 +55,13 @@ describe('get_pipeline', () => { }); it('returns correct stats', () => { - const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeboundsInMillis); + const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds); expect(result).to.eql({ events_in: 10000, events_out: 9000, duration_in_millis: 18000, - events_per_millisecond: 0.000011111111111111112, + events_in_per_millisecond: 0.011111111111111112, + events_out_per_millisecond: 0.01, millis_per_event: 1.8, percent_of_total_processor_duration: 0.75 }); @@ -75,12 +76,13 @@ describe('get_pipeline', () => { }); it('returns correct stats', () => { - const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeboundsInMillis); + const result = _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationInMillis, timeseriesIntervalInSeconds); expect(result).to.eql({ events_in: 10000, events_out: 9000, duration_in_millis: 18000, - events_per_millisecond: 0.000011111111111111112, + events_in_per_millisecond: 0.011111111111111112, + events_out_per_millisecond: 0.01, millis_per_event: 1.8, percent_of_total_processor_duration: 0.75 }); @@ -289,7 +291,7 @@ describe('get_pipeline', () => { max: 1516135440463 } }, - events_per_millisecond: { + events_out_per_millisecond: { data: [ [ 1516131120000, 0.03333333333333333 ], [ 1516131180000, 0.06666666666666667 ] @@ -367,7 +369,17 @@ describe('get_pipeline', () => { max: 1516135440463 } }, - events_per_millisecond: { + events_in_per_millisecond: { + data: [ + [1516131120000, 0.03333333333333333], + [1516131180000, 0.06666666666666667] + ], + timeRange: { + min: 1516131138639, + max: 1516135440463 + } + }, + events_out_per_millisecond: { data: [ [ 1516131120000, 0.03333333333333333 ], [ 1516131180000, 0.06666666666666667 ] diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_logstash_for_clusters.js b/x-pack/plugins/monitoring/server/lib/logstash/get_logstash_for_clusters.js index 22c0838f866003..fae1a9431135d8 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_logstash_for_clusters.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_logstash_for_clusters.js @@ -8,7 +8,7 @@ import Promise from 'bluebird'; import { get } from 'lodash'; import { checkParam } from '../error_missing_required'; import { createQuery } from '../create_query.js'; -import { ElasticsearchMetric } from '../metrics'; +import { LogstashClusterMetric } from '../metrics'; import { LOGSTASH } from '../../../common/constants'; const { @@ -47,17 +47,17 @@ export function getLogstashForClusters(req, lsIndexPattern, clusters) { return Promise.map(clusters, cluster => { const clusterUuid = cluster.cluster_uuid; - const metric = ElasticsearchMetric.getMetricFields(); const params = { index: lsIndexPattern, size: 0, ignoreUnavailable: true, body: { query: createQuery({ + type: 'logstash_stats', start, end, clusterUuid, - metric + metric: LogstashClusterMetric.getMetricFields() }), aggs: { logstash_uuids: { diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_nodes.js b/x-pack/plugins/monitoring/server/lib/logstash/get_nodes.js index f2941eb69da77f..055833f3743ed2 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_nodes.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_nodes.js @@ -9,7 +9,7 @@ import moment from 'moment'; import { checkParam } from '../error_missing_required'; import { createQuery } from '../create_query'; import { calculateAvailability } from '../calculate_availability'; -import { ElasticsearchMetric } from '../metrics'; +import { LogstashMetric } from '../metrics'; /* * Get detailed info for Logstash's in the cluster @@ -38,7 +38,7 @@ export function getNodes(req, lsIndexPattern, { clusterUuid }) { start, end, clusterUuid, - metric: ElasticsearchMetric.getMetricFields(), + metric: LogstashMetric.getMetricFields(), type: 'logstash_stats' }), collapse: { diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js index 8680eeb573b69d..d0002f07ccda30 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline.js @@ -17,6 +17,8 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI const isInput = vertex.plugin_type === 'input'; const isProcessor = vertex.plugin_type === 'filter' || vertex.plugin_type === 'output'; + const timeseriesIntervalInMillis = timeseriesIntervalInSeconds * 1000; + const eventsInTotal = vertexStatsBucket.events_in_total.value; const eventsOutTotal = get(vertexStatsBucket, 'events_out_total.value', null); @@ -24,6 +26,9 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI const inputStats = {}; const processorStats = {}; + const eventsProcessedStats = { + events_out_per_millisecond: eventsOutTotal / timeseriesIntervalInMillis + }; let eventsTotal; @@ -36,16 +41,17 @@ export function _vertexStats(vertex, vertexStatsBucket, totalProcessorsDurationI if (isProcessor) { eventsTotal = eventsInTotal; processorStats.percent_of_total_processor_duration = durationInMillis / totalProcessorsDurationInMillis; + eventsProcessedStats.events_in_per_millisecond = eventsInTotal / timeseriesIntervalInMillis; } return { events_in: eventsInTotal, events_out: eventsOutTotal, duration_in_millis: durationInMillis, - events_per_millisecond: eventsTotal / (timeseriesIntervalInSeconds * 1000), millis_per_event: durationInMillis / eventsTotal, ...inputStats, - ...processorStats + ...processorStats, + ...eventsProcessedStats }; } diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js index 173bce4dd1c46b..ccccb84ceb9a1a 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_state_document.js @@ -5,7 +5,7 @@ */ import { createQuery } from '../create_query'; -import { ElasticsearchMetric } from '../metrics'; +import { LogstashMetric } from '../metrics'; import { get } from 'lodash'; export async function getPipelineStateDocument(callWithRequest, req, logstashIndexPattern, @@ -22,7 +22,7 @@ export async function getPipelineStateDocument(callWithRequest, req, logstashInd // that could result in us being unable to render the graph // Use the logstash_stats documents to determine whether the instance is up/down type: 'logstash_state', - metric: ElasticsearchMetric.getMetricFields(), + metric: LogstashMetric.getMetricFields(), clusterUuid, filters }); diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js index 77d3048a10abd7..809810216c1054 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_stats_aggregation.js @@ -6,7 +6,7 @@ import { get, last } from 'lodash'; import { createQuery } from '../create_query'; -import { ElasticsearchMetric } from '../metrics'; +import { LogstashMetric } from '../metrics'; function scalarCounterAggregation(field, fieldPath, ephemeralIdField, maxBucketSize) { const fullPath = `${fieldPath}.${field}`; @@ -166,7 +166,7 @@ export async function getPipelineStatsAggregation(callWithRequest, req, logstash type: 'logstash_stats', start, end, - metric: ElasticsearchMetric.getMetricFields(), + metric: LogstashMetric.getMetricFields(), clusterUuid, filters }); diff --git a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js index 7cc6e39b327c6d..b66aad3dcfcfee 100644 --- a/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js +++ b/x-pack/plugins/monitoring/server/lib/logstash/get_pipeline_versions.js @@ -5,7 +5,7 @@ */ import { createQuery } from '../create_query'; -import { ElasticsearchMetric } from '../metrics'; +import { LogstashMetric } from '../metrics'; import { get } from 'lodash'; import { checkParam } from '../error_missing_required'; @@ -29,7 +29,7 @@ function fetchPipelineVersions(...args) { ]; const query = createQuery({ type: 'logstash_stats', - metric: ElasticsearchMetric.getMetricFields(), + metric: LogstashMetric.getMetricFields(), clusterUuid, filters }); diff --git a/x-pack/plugins/monitoring/server/lib/metrics/__test__/__snapshots__/metrics.test.js.snap b/x-pack/plugins/monitoring/server/lib/metrics/__test__/__snapshots__/metrics.test.js.snap index 27d9c13c78e1d0..f164fac18882ae 100644 --- a/x-pack/plugins/monitoring/server/lib/metrics/__test__/__snapshots__/metrics.test.js.snap +++ b/x-pack/plugins/monitoring/server/lib/metrics/__test__/__snapshots__/metrics.test.js.snap @@ -2,7 +2,7 @@ exports[`Metrics should export metric objects that match a snapshot 1`] = ` Object { - "beat_bytes_written": Object { + "beat_bytes_written": BeatsByteRateMetric { "app": "beats", "derivative": true, "description": "Bytes written to the output (consists of size of network headers and compressed payload)", @@ -13,9 +13,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Throughput", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_cluster_output_events_ack_rate": Object { + "beat_cluster_output_events_ack_rate": BeatsEventsRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -56,7 +56,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_output_events_dropped_rate": Object { + "beat_cluster_output_events_dropped_rate": BeatsEventsRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -97,7 +97,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_output_events_total": Object { + "beat_cluster_output_events_total": BeatsEventsRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -138,7 +138,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_output_read_bytes_rate": Object { + "beat_cluster_output_read_bytes_rate": BeatsByteRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -179,7 +179,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_output_receiving_errors": Object { + "beat_cluster_output_receiving_errors": BeatsEventsRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -220,7 +220,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_output_sending_errors": Object { + "beat_cluster_output_sending_errors": BeatsEventsRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -261,7 +261,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_output_write_bytes_rate": Object { + "beat_cluster_output_write_bytes_rate": BeatsByteRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -302,7 +302,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_pipeline_events_dropped_rate": Object { + "beat_cluster_pipeline_events_dropped_rate": BeatsEventsRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -343,7 +343,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_pipeline_events_emitted_rate": Object { + "beat_cluster_pipeline_events_emitted_rate": BeatsEventsRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -384,7 +384,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_pipeline_events_failed_rate": Object { + "beat_cluster_pipeline_events_failed_rate": BeatsEventsRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -425,7 +425,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_pipeline_events_retry_rate": Object { + "beat_cluster_pipeline_events_retry_rate": BeatsEventsRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -466,7 +466,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cluster_pipeline_events_total_rate": Object { + "beat_cluster_pipeline_events_total_rate": BeatsEventsRateClusterMetric { "aggs": Object { "beats_uuids": Object { "aggs": Object { @@ -507,7 +507,7 @@ Object { "units": "/s", "uuidField": "cluster_uuid", }, - "beat_cpu_utilization": Object { + "beat_cpu_utilization": BeatsCpuUtilizationMetric { "app": "beats", "calculation": [Function], "derivative": true, @@ -519,9 +519,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "CPU Utilization", "units": "%", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_mem_alloc": Object { + "beat_mem_alloc": BeatsMetric { "app": "beats", "derivative": false, "description": "Private memory in active use by the Beat", @@ -532,9 +532,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Memory", "units": "B", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_mem_gc_next": Object { + "beat_mem_gc_next": BeatsMetric { "app": "beats", "derivative": false, "description": "Limit of allocated memory at which garbage collection will occur", @@ -545,9 +545,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Memory", "units": "B", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_mem_rss": Object { + "beat_mem_rss": BeatsMetric { "app": "beats", "derivative": false, "description": "Resident set size of memory reserved by the Beat from the OS", @@ -558,9 +558,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Memory", "units": "B", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_output_events_ack_rate": Object { + "beat_output_events_ack_rate": BeatsEventsRateMetric { "app": "beats", "derivative": true, "description": "Events acknowledged by the output (includes events dropped by the output)", @@ -571,9 +571,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Events Rate", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_output_events_dropped_rate": Object { + "beat_output_events_dropped_rate": BeatsEventsRateMetric { "app": "beats", "derivative": true, "description": "(Fatal drop) Events dropped by the output as being \\"invalid.\\" The output still acknowledges the event for the Beat to remove it from the queue.", @@ -584,9 +584,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Fail Rates", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_output_events_total": Object { + "beat_output_events_total": BeatsEventsRateMetric { "app": "beats", "derivative": true, "description": "Events processed by the output (including retries)", @@ -597,9 +597,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Events Rate", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_output_receiving_errors": Object { + "beat_output_receiving_errors": BeatsEventsRateMetric { "app": "beats", "derivative": true, "description": "Errors in reading the response from the output", @@ -610,9 +610,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Output Errors", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_output_sending_errors": Object { + "beat_output_sending_errors": BeatsEventsRateMetric { "app": "beats", "derivative": true, "description": "Errors in writing the response from the output", @@ -623,9 +623,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Output Errors", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_output_write_bytes_rate": Object { + "beat_output_write_bytes_rate": BeatsByteRateMetric { "app": "beats", "derivative": true, "description": "Bytes read in response from the output", @@ -636,9 +636,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Throughput", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_pipeline_events_dropped_rate": Object { + "beat_pipeline_events_dropped_rate": BeatsEventsRateMetric { "app": "beats", "derivative": true, "description": "Events that have been dropped after N retries (N = max_retries setting)", @@ -649,9 +649,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Fail Rates", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_pipeline_events_emitted_rate": Object { + "beat_pipeline_events_emitted_rate": BeatsEventsRateMetric { "app": "beats", "derivative": true, "description": "Events added to the event pipeline queue", @@ -662,9 +662,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Events Rate", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_pipeline_events_failed_rate": Object { + "beat_pipeline_events_failed_rate": BeatsEventsRateMetric { "app": "beats", "derivative": true, "description": "Failures that happened before event was added to the publishing pipeline (output was disabled or publisher client closed)", @@ -675,9 +675,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Fail Rates", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_pipeline_events_retry_rate": Object { + "beat_pipeline_events_retry_rate": BeatsEventsRateMetric { "app": "beats", "derivative": true, "description": "Events in the pipeline that are trying again to be sent to the output", @@ -688,9 +688,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Fail Rates", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_pipeline_events_total_rate": Object { + "beat_pipeline_events_total_rate": BeatsEventsRateMetric { "app": "beats", "derivative": true, "description": "New events sent to the publishing pipeline", @@ -701,9 +701,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "Events Rate", "units": "/s", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_system_os_load_1": Object { + "beat_system_os_load_1": BeatsMetric { "app": "beats", "derivative": false, "description": "Load average over the last 1 minute", @@ -714,9 +714,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "System Load", "units": "", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_system_os_load_15": Object { + "beat_system_os_load_15": BeatsMetric { "app": "beats", "derivative": false, "description": "Load average over the last 15 minutes", @@ -727,9 +727,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "System Load", "units": "", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "beat_system_os_load_5": Object { + "beat_system_os_load_5": BeatsMetric { "app": "beats", "derivative": false, "description": "Load average over the last 5 minutes", @@ -740,9 +740,9 @@ Object { "timestampField": "beats_stats.timestamp", "title": "System Load", "units": "", - "uuidField": "cluster_uuid", + "uuidField": "beats_stats.beat.uuid", }, - "cluster_index_latency": Object { + "cluster_index_latency": LatencyMetric { "aggs": Object { "event_time_in_millis": Object { "max": Object { @@ -782,7 +782,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "cluster_index_request_rate_primary": Object { + "cluster_index_request_rate_primary": RequestRateMetric { "app": "elasticsearch", "derivative": true, "description": "Number of documents being indexed for primary shards.", @@ -796,7 +796,7 @@ Object { "units": "/s", "uuidField": "source_node.uuid", }, - "cluster_index_request_rate_total": Object { + "cluster_index_request_rate_total": RequestRateMetric { "app": "elasticsearch", "derivative": true, "description": "Number of documents being indexed for primary and replica shards.", @@ -810,7 +810,7 @@ Object { "units": "/s", "uuidField": "source_node.uuid", }, - "cluster_query_latency": Object { + "cluster_query_latency": LatencyMetric { "aggs": Object { "event_time_in_millis": Object { "max": Object { @@ -850,7 +850,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "cluster_search_request_rate": Object { + "cluster_search_request_rate": RequestRateMetric { "app": "elasticsearch", "derivative": true, "description": "Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!", @@ -864,7 +864,7 @@ Object { "units": "/s", "uuidField": "source_node.uuid", }, - "index_document_count": Object { + "index_document_count": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Total number of documents, only including primary shards.", @@ -877,7 +877,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "index_indexing_primaries_time": Object { + "index_indexing_primaries_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of time spent performing index operations on primary shards only.", @@ -891,7 +891,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "index_indexing_total": Object { + "index_indexing_total": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of indexing operations.", @@ -905,7 +905,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "index_indexing_total_time": Object { + "index_indexing_total_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of time spent performing index operations on primary and replica shards.", @@ -919,7 +919,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "index_latency": Object { + "index_latency": LatencyMetric { "aggs": Object { "event_time_in_millis": Object { "max": Object { @@ -959,7 +959,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "index_mem_doc_values": Object { + "index_mem_doc_values": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Doc Values. This is a part of Lucene Total.", @@ -973,7 +973,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_fielddata": Object { + "index_mem_fielddata": IndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Fielddata (e.g., global ordinals or explicitly enabled fielddata on text fields). This is for the same shards, but not a part of Lucene Total.", @@ -987,7 +987,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_fixed_bit_set": Object { + "index_mem_fixed_bit_set": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.", @@ -1001,7 +1001,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_norms": Object { + "index_mem_norms": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.", @@ -1015,7 +1015,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_overall": Object { + "index_mem_overall": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", @@ -1029,7 +1029,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_overall_1": Object { + "index_mem_overall_1": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", @@ -1043,7 +1043,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_overall_2": Object { + "index_mem_overall_2": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", @@ -1057,7 +1057,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_overall_3": Object { + "index_mem_overall_3": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", @@ -1071,7 +1071,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_points": Object { + "index_mem_points": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.", @@ -1085,7 +1085,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_query_cache": Object { + "index_mem_query_cache": IndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Query Cache (e.g., cached filters). This is for the same shards, but not a part of Lucene Total.", @@ -1099,7 +1099,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_request_cache": Object { + "index_mem_request_cache": IndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Request Cache (e.g., instant aggregations). This is for the same shards, but not a part of Lucene Total.", @@ -1113,7 +1113,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_stored_fields": Object { + "index_mem_stored_fields": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.", @@ -1127,7 +1127,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_term_vectors": Object { + "index_mem_term_vectors": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Term Vectors. This is a part of Lucene Total.", @@ -1141,7 +1141,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_terms": Object { + "index_mem_terms": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Terms (e.g., text). This is a part of Lucene Total.", @@ -1155,7 +1155,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_versions": Object { + "index_mem_versions": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Versioning (e.g., updates and deletes). This is NOT a part of Lucene Total.", @@ -1169,7 +1169,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_writer": Object { + "index_mem_writer": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by the Index Writer. This is NOT a part of Lucene Total.", @@ -1183,7 +1183,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_merge_rate": Object { + "index_merge_rate": RequestRateMetric { "app": "elasticsearch", "derivative": true, "description": "Amount in bytes of merged segments. Larger numbers indicate heavier disk activity.", @@ -1196,7 +1196,7 @@ Object { "units": "/s", "uuidField": "source_node.uuid", }, - "index_refresh_time": Object { + "index_refresh_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Time spent on Elasticsearch refresh for primary and replica shards.", @@ -1209,7 +1209,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "index_request_rate_primary": Object { + "index_request_rate_primary": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Number of documents being indexed for primary shards.", @@ -1223,7 +1223,7 @@ Object { "units": "/s", "uuidField": "source_node.uuid", }, - "index_request_rate_total": Object { + "index_request_rate_total": RequestRateMetric { "app": "elasticsearch", "derivative": true, "description": "Number of documents being indexed for primary and replica shards.", @@ -1237,7 +1237,7 @@ Object { "units": "/s", "uuidField": "source_node.uuid", }, - "index_search_request_rate": Object { + "index_search_request_rate": RequestRateMetric { "app": "elasticsearch", "derivative": true, "description": "Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!", @@ -1251,7 +1251,7 @@ Object { "units": "/s", "uuidField": "source_node.uuid", }, - "index_searching_time": Object { + "index_searching_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of time spent performing search operations (per shard).", @@ -1265,7 +1265,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "index_searching_total": Object { + "index_searching_total": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of search operations (per shard).", @@ -1279,7 +1279,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "index_segment_count_primaries": Object { + "index_segment_count_primaries": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Number of segments for primary shards.", @@ -1293,7 +1293,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "index_segment_count_total": Object { + "index_segment_count_total": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Number of segments for primary and replica shards.", @@ -1307,7 +1307,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "index_segment_merge_primaries_size": Object { + "index_segment_merge_primaries_size": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Size of merges on primary shards.", @@ -1321,7 +1321,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_segment_merge_total_size": Object { + "index_segment_merge_total_size": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Size of merges on primary and replica shards.", @@ -1335,7 +1335,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_segment_refresh_primaries_time": Object { + "index_segment_refresh_primaries_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of time spent to perform refresh operations on primary shards.", @@ -1349,7 +1349,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "index_segment_refresh_total_time": Object { + "index_segment_refresh_total_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of time spent to perform refresh operations on primary and replica shards.", @@ -1363,7 +1363,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "index_store_primaries_size": Object { + "index_store_primaries_size": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Size of primary shards on disk.", @@ -1377,7 +1377,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_store_total_size": Object { + "index_store_total_size": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Size of primary and replica shards on disk.", @@ -1391,7 +1391,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_throttle_time": Object { + "index_throttle_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of time spent with index throttling, which indicates slow merging.", @@ -1404,7 +1404,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "index_throttling_indexing_primaries_time": Object { + "index_throttling_indexing_primaries_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of time spent throttling index operations on primary shards.", @@ -1418,7 +1418,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "index_throttling_indexing_total_time": Object { + "index_throttling_indexing_total_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of time spent throttling index operations on primary and replica shards.", @@ -1432,7 +1432,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "kibana_average_concurrent_connections": Object { + "kibana_average_concurrent_connections": KibanaMetric { "app": "kibana", "derivative": false, "description": "Total number of open socket connections to the Kibana instance.", @@ -1444,7 +1444,7 @@ Object { "units": "", "uuidField": "kibana_stats.kibana.uuid", }, - "kibana_average_response_times": Object { + "kibana_average_response_times": KibanaMetric { "app": "kibana", "derivative": false, "description": "Average response time for client requests to the Kibana instance.", @@ -1457,7 +1457,7 @@ Object { "units": "ms", "uuidField": "kibana_stats.kibana.uuid", }, - "kibana_cluster_average_response_times": Object { + "kibana_cluster_average_response_times": KibanaEventsRateClusterMetric { "aggs": Object { "event_rate": Object { "sum_bucket": Object { @@ -1498,7 +1498,7 @@ Object { "units": "ms", "uuidField": "cluster_uuid", }, - "kibana_cluster_max_response_times": Object { + "kibana_cluster_max_response_times": KibanaEventsRateClusterMetric { "aggs": Object { "event_rate": Object { "sum_bucket": Object { @@ -1539,7 +1539,7 @@ Object { "units": "ms", "uuidField": "cluster_uuid", }, - "kibana_cluster_requests": Object { + "kibana_cluster_requests": KibanaEventsRateClusterMetric { "aggs": Object { "event_rate": Object { "sum_bucket": Object { @@ -1579,7 +1579,7 @@ Object { "units": "", "uuidField": "cluster_uuid", }, - "kibana_max_response_times": Object { + "kibana_max_response_times": KibanaMetric { "app": "kibana", "derivative": false, "description": "Maximum response time for client requests to the Kibana instance.", @@ -1592,7 +1592,7 @@ Object { "units": "ms", "uuidField": "kibana_stats.kibana.uuid", }, - "kibana_memory_heap_size_limit": Object { + "kibana_memory_heap_size_limit": KibanaMetric { "app": "kibana", "derivative": false, "description": "Limit of memory usage before garbage collection.", @@ -1605,7 +1605,7 @@ Object { "units": "B", "uuidField": "kibana_stats.kibana.uuid", }, - "kibana_memory_size": Object { + "kibana_memory_size": KibanaMetric { "app": "kibana", "derivative": false, "description": "Total heap used by Kibana running in Node.js.", @@ -1618,7 +1618,7 @@ Object { "units": "B", "uuidField": "kibana_stats.kibana.uuid", }, - "kibana_os_load_15m": Object { + "kibana_os_load_15m": KibanaMetric { "app": "kibana", "derivative": false, "description": "Load average over the last 15 minutes.", @@ -1631,7 +1631,7 @@ Object { "units": "", "uuidField": "kibana_stats.kibana.uuid", }, - "kibana_os_load_1m": Object { + "kibana_os_load_1m": KibanaMetric { "app": "kibana", "derivative": false, "description": "Load average over the last minute.", @@ -1644,7 +1644,7 @@ Object { "units": "", "uuidField": "kibana_stats.kibana.uuid", }, - "kibana_os_load_5m": Object { + "kibana_os_load_5m": KibanaMetric { "app": "kibana", "derivative": false, "description": "Load average over the last 5 minutes.", @@ -1657,7 +1657,7 @@ Object { "units": "", "uuidField": "kibana_stats.kibana.uuid", }, - "kibana_process_delay": Object { + "kibana_process_delay": KibanaMetric { "app": "kibana", "derivative": false, "description": "Delay in Kibana server event loops. Longer delays may indicate blocking events in server thread, such as synchronous functions taking large amount of CPU time.", @@ -1669,7 +1669,7 @@ Object { "units": "ms", "uuidField": "kibana_stats.kibana.uuid", }, - "kibana_requests": Object { + "kibana_requests": KibanaMetric { "app": "kibana", "derivative": false, "description": "Total number of client requests received by the Kibana instance.", @@ -1681,7 +1681,7 @@ Object { "units": "", "uuidField": "kibana_stats.kibana.uuid", }, - "logstash_cluster_events_input_rate": Object { + "logstash_cluster_events_input_rate": LogstashEventsRateClusterMetric { "aggs": Object { "event_rate": Object { "sum_bucket": Object { @@ -1719,8 +1719,9 @@ Object { "metricAgg": "max", "timestampField": "logstash_stats.timestamp", "units": "/s", + "uuidField": "cluster_uuid", }, - "logstash_cluster_events_latency": Object { + "logstash_cluster_events_latency": LogstashEventsLatencyClusterMetric { "aggs": Object { "events_time_in_millis": Object { "sum_bucket": Object { @@ -1777,8 +1778,9 @@ Object { "metricAgg": "max", "timestampField": "logstash_stats.timestamp", "units": "ms", + "uuidField": "cluster_uuid", }, - "logstash_cluster_events_output_rate": Object { + "logstash_cluster_events_output_rate": LogstashEventsRateClusterMetric { "aggs": Object { "event_rate": Object { "sum_bucket": Object { @@ -1816,8 +1818,9 @@ Object { "metricAgg": "max", "timestampField": "logstash_stats.timestamp", "units": "/s", + "uuidField": "cluster_uuid", }, - "logstash_cluster_pipeline_nodes_count": Object { + "logstash_cluster_pipeline_nodes_count": LogstashPipelineNodeCountMetric { "app": "logstash", "calculation": [Function], "dateHistogramSubAggs": Object { @@ -1856,7 +1859,7 @@ Object { "units": "", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_cluster_pipeline_throughput": Object { + "logstash_cluster_pipeline_throughput": LogstashPipelineThroughputMetric { "app": "logstash", "calculation": [Function], "dateHistogramSubAggs": Object { @@ -1925,7 +1928,7 @@ Object { "units": "e/s", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_events_input_rate": Object { + "logstash_events_input_rate": LogstashEventsRateMetric { "app": "logstash", "derivative": true, "description": "Number of events received per second by the Logstash node at the inputs stage.", @@ -1937,7 +1940,7 @@ Object { "units": "/s", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_events_latency": Object { + "logstash_events_latency": LogstashEventsLatencyMetric { "aggs": Object { "events_time_in_millis": Object { "max": Object { @@ -1976,7 +1979,7 @@ Object { "units": "ms", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_events_output_rate": Object { + "logstash_events_output_rate": LogstashEventsRateMetric { "app": "logstash", "derivative": true, "description": "Number of events emitted per second by the Logstash node at the outputs stage.", @@ -1988,7 +1991,7 @@ Object { "units": "/s", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_cgroup_periods": Object { + "logstash_node_cgroup_periods": LogstashMetric { "app": "logstash", "derivative": true, "description": "The number of sampling periods from the Completely Fair Scheduler (CFS). Compare against the number of times throttled.", @@ -2001,7 +2004,7 @@ Object { "units": "", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_cgroup_quota": Object { + "logstash_node_cgroup_quota": QuotaMetric { "aggs": Object { "periods": Object { "max": Object { @@ -2050,7 +2053,7 @@ Object { "usageField": "cpuacct.usage_nanos", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_cgroup_quota_as_cpu_utilization": Object { + "logstash_node_cgroup_quota_as_cpu_utilization": QuotaMetric { "aggs": Object { "periods": Object { "max": Object { @@ -2098,7 +2101,7 @@ Object { "usageField": "cpuacct.usage_nanos", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_cgroup_throttled": Object { + "logstash_node_cgroup_throttled": LogstashMetric { "app": "logstash", "derivative": true, "description": "The amount of throttled time, reported in nanoseconds, of the Cgroup.", @@ -2111,7 +2114,7 @@ Object { "units": "ns", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_cgroup_throttled_count": Object { + "logstash_node_cgroup_throttled_count": LogstashMetric { "app": "logstash", "derivative": true, "description": "The number of times that the CPU was throttled by the Cgroup.", @@ -2124,7 +2127,7 @@ Object { "units": "", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_cgroup_usage": Object { + "logstash_node_cgroup_usage": LogstashMetric { "app": "logstash", "derivative": true, "description": "The usage, reported in nanoseconds, of the Cgroup. Compare this with the throttling to discover issues.", @@ -2137,7 +2140,7 @@ Object { "units": "ns", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_cpu_utilization": Object { + "logstash_node_cpu_utilization": LogstashMetric { "app": "logstash", "derivative": false, "description": "Percentage of CPU usage reported by the OS (100% is the max).", @@ -2149,7 +2152,7 @@ Object { "units": "%", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_jvm_mem_max_in_bytes": Object { + "logstash_node_jvm_mem_max_in_bytes": LogstashMetric { "app": "logstash", "derivative": false, "description": "Total heap available to Logstash running in the JVM.", @@ -2162,7 +2165,7 @@ Object { "units": "B", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_jvm_mem_used_in_bytes": Object { + "logstash_node_jvm_mem_used_in_bytes": LogstashMetric { "app": "logstash", "derivative": false, "description": "Total heap used by Logstash running in the JVM.", @@ -2175,7 +2178,7 @@ Object { "units": "B", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_pipeline_nodes_count": Object { + "logstash_node_pipeline_nodes_count": LogstashPipelineNodeCountMetric { "app": "logstash", "calculation": [Function], "dateHistogramSubAggs": Object { @@ -2214,7 +2217,7 @@ Object { "units": "", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_node_pipeline_throughput": Object { + "logstash_node_pipeline_throughput": LogstashPipelineThroughputMetric { "app": "logstash", "calculation": [Function], "dateHistogramSubAggs": Object { @@ -2283,7 +2286,7 @@ Object { "units": "e/s", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_os_load_15m": Object { + "logstash_os_load_15m": LogstashMetric { "app": "logstash", "derivative": false, "description": "Load average over the last 15 minutes.", @@ -2296,7 +2299,7 @@ Object { "units": "", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_os_load_1m": Object { + "logstash_os_load_1m": LogstashMetric { "app": "logstash", "derivative": false, "description": "Load average over the last minute.", @@ -2309,7 +2312,7 @@ Object { "units": "", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_os_load_5m": Object { + "logstash_os_load_5m": LogstashMetric { "app": "logstash", "derivative": false, "description": "Load average over the last 5 minutes.", @@ -2322,7 +2325,7 @@ Object { "units": "", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_pipeline_max_queue_size": Object { + "logstash_pipeline_max_queue_size": LogstashPipelineQueueSizeMetric { "app": "logstash", "calculation": [Function], "dateHistogramSubAggs": Object { @@ -2361,7 +2364,7 @@ Object { "units": "B", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_pipeline_queue_size": Object { + "logstash_pipeline_queue_size": LogstashPipelineQueueSizeMetric { "app": "logstash", "calculation": [Function], "dateHistogramSubAggs": Object { @@ -2401,7 +2404,7 @@ Object { "units": "B", "uuidField": "logstash_stats.logstash.uuid", }, - "logstash_queue_events_count": Object { + "logstash_queue_events_count": LogstashMetric { "app": "logstash", "derivative": false, "description": "Average number of events in the persistent queue waiting to be processed by the filter and output stages.", @@ -2414,7 +2417,7 @@ Object { "units": "", "uuidField": "logstash_stats.logstash.uuid", }, - "node_cgroup_periods": Object { + "node_cgroup_periods": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "The number of sampling periods from the Completely Fair Scheduler (CFS). Compare against the number of times throttled.", @@ -2428,7 +2431,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_cgroup_quota": Object { + "node_cgroup_quota": QuotaMetric { "aggs": Object { "periods": Object { "max": Object { @@ -2478,7 +2481,7 @@ Object { "usageField": "cpuacct.usage_nanos", "uuidField": "source_node.uuid", }, - "node_cgroup_quota_as_cpu_utilization": Object { + "node_cgroup_quota_as_cpu_utilization": QuotaMetric { "aggs": Object { "periods": Object { "max": Object { @@ -2527,7 +2530,7 @@ Object { "usageField": "cpuacct.usage_nanos", "uuidField": "source_node.uuid", }, - "node_cgroup_throttled": Object { + "node_cgroup_throttled": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "The amount of throttled time, reported in nanoseconds, of the Cgroup.", @@ -2541,7 +2544,7 @@ Object { "units": "ns", "uuidField": "source_node.uuid", }, - "node_cgroup_throttled_count": Object { + "node_cgroup_throttled_count": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "The number of times that the CPU was throttled by the Cgroup.", @@ -2555,7 +2558,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_cgroup_usage": Object { + "node_cgroup_usage": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "The usage, reported in nanoseconds, of the Cgroup. Compare this with the throttling to discover issues.", @@ -2569,7 +2572,7 @@ Object { "units": "ns", "uuidField": "source_node.uuid", }, - "node_cpu_utilization": Object { + "node_cpu_utilization": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Percentage of CPU usage for the Elasticsearch process.", @@ -2582,7 +2585,7 @@ Object { "units": "%", "uuidField": "source_node.uuid", }, - "node_free_space": Object { + "node_free_space": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Free disk space available on the node.", @@ -2595,7 +2598,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_index_latency": Object { + "node_index_latency": LatencyMetric { "aggs": Object { "event_time_in_millis": Object { "max": Object { @@ -2636,7 +2639,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "node_index_mem_doc_values": Object { + "node_index_mem_doc_values": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Doc Values. This is a part of Lucene Total.", @@ -2650,7 +2653,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_fielddata": Object { + "node_index_mem_fielddata": IndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Fielddata (e.g., global ordinals or explicitly enabled fielddata on text fields). This is for the same shards, but not a part of Lucene Total.", @@ -2664,7 +2667,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_fixed_bit_set": Object { + "node_index_mem_fixed_bit_set": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.", @@ -2678,7 +2681,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_norms": Object { + "node_index_mem_norms": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.", @@ -2692,7 +2695,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_overall": Object { + "node_index_mem_overall": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", @@ -2706,7 +2709,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_overall_1": Object { + "node_index_mem_overall_1": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", @@ -2720,7 +2723,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_overall_2": Object { + "node_index_mem_overall_2": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", @@ -2734,7 +2737,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_overall_3": Object { + "node_index_mem_overall_3": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", @@ -2748,7 +2751,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_points": Object { + "node_index_mem_points": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.", @@ -2762,7 +2765,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_query_cache": Object { + "node_index_mem_query_cache": IndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Query Cache (e.g., cached filters). This is for the same shards, but not a part of Lucene Total.", @@ -2776,7 +2779,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_request_cache": Object { + "node_index_mem_request_cache": IndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Request Cache (e.g., instant aggregations). This is for the same shards, but not a part of Lucene Total.", @@ -2790,7 +2793,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_stored_fields": Object { + "node_index_mem_stored_fields": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.", @@ -2804,7 +2807,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_term_vectors": Object { + "node_index_mem_term_vectors": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Term Vectors. This is a part of Lucene Total.", @@ -2818,7 +2821,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_terms": Object { + "node_index_mem_terms": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Terms (e.g., text). This is a part of Lucene Total.", @@ -2832,7 +2835,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_versions": Object { + "node_index_mem_versions": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by Versioning (e.g., updates and deletes). This is NOT a part of Lucene Total.", @@ -2846,7 +2849,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_writer": Object { + "node_index_mem_writer": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, "description": "Heap memory used by the Index Writer. This is NOT a part of Lucene Total.", @@ -2860,7 +2863,37 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_threads_get_queue": Object { + "node_index_threads_bulk_queue": ElasticsearchMetric { + "app": "elasticsearch", + "derivative": true, + "description": "Number of bulk operations in the queue.", + "field": "node_stats.thread_pool.bulk.queue", + "format": "0,0.[00]", + "label": "Bulk Queue", + "metricAgg": "max", + "min": 0, + "timestampField": "timestamp", + "title": "Indexing Threads", + "type": "node", + "units": "", + "uuidField": "source_node.uuid", + }, + "node_index_threads_bulk_rejected": ElasticsearchMetric { + "app": "elasticsearch", + "derivative": true, + "description": "Number of bulk operations that have been rejected, which occurs when the queue is full.", + "field": "node_stats.thread_pool.bulk.rejected", + "format": "0,0.[00]", + "label": "Bulk Rejections", + "metricAgg": "max", + "min": 0, + "timestampField": "timestamp", + "title": "Indexing Threads", + "type": "node", + "units": "", + "uuidField": "source_node.uuid", + }, + "node_index_threads_get_queue": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Number of GET operations in the queue.", @@ -2875,7 +2908,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_index_threads_get_rejected": Object { + "node_index_threads_get_rejected": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Number of GET operations that have been rejected, which occurs when the queue is full.", @@ -2890,122 +2923,67 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_index_threads_search_queue": Object { + "node_index_threads_index_queue": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, - "description": "Number of search operations in the queue (e.g., shard level searches).", - "field": "node_stats.thread_pool.search.queue", + "description": "Number of non-bulk, index operations in the queue.", + "field": "node_stats.thread_pool.index.queue", "format": "0,0.[00]", - "label": "Search Queue", + "label": "Index Queue", "metricAgg": "max", "min": 0, "timestampField": "timestamp", - "title": "Read Threads", + "title": "Indexing Threads", "type": "node", "units": "", "uuidField": "source_node.uuid", }, - "node_index_threads_search_rejected": Object { + "node_index_threads_index_rejected": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, - "description": "Number of search operations that have been rejected, which occurs when the queue is full.", - "field": "node_stats.thread_pool.search.rejected", + "description": "Number of non-bulk, index operations that have been rejected, which occurs when the queue is full. Generally indicates that bulk should be used.", + "field": "node_stats.thread_pool.index.rejected", "format": "0,0.[00]", - "label": "Search Rejections", + "label": "Index Rejections", "metricAgg": "max", "min": 0, "timestampField": "timestamp", - "title": "Read Threads", + "title": "Indexing Threads", "type": "node", "units": "", "uuidField": "source_node.uuid", }, - "node_index_threads_write_queue": Object { + "node_index_threads_search_queue": ElasticsearchMetric { "app": "elasticsearch", - "calculation": [Function], - "dateHistogramSubAggs": Object { - "bulk": Object { - "max": Object { - "field": "node_stats.thread_pool.bulk.queue", - }, - }, - "index": Object { - "max": Object { - "field": "node_stats.thread_pool.index.queue", - }, - }, - "write": Object { - "max": Object { - "field": "node_stats.thread_pool.write.queue", - }, - }, - }, - "derivative": false, - "description": "Number of index, bulk, and write operations in the queue. The bulk threadpool was renamed to write in 6.3, and the index threadpool is deprecated.", - "field": "node_stats.thread_pool.write.queue", - "format": "0.[00]", - "label": "Write Queue", + "derivative": true, + "description": "Number of search operations in the queue (e.g., shard level searches).", + "field": "node_stats.thread_pool.search.queue", + "format": "0,0.[00]", + "label": "Search Queue", "metricAgg": "max", + "min": 0, "timestampField": "timestamp", - "title": "Indexing Threads", + "title": "Read Threads", "type": "node", "units": "", "uuidField": "source_node.uuid", }, - "node_index_threads_write_rejected": Object { + "node_index_threads_search_rejected": ElasticsearchMetric { "app": "elasticsearch", - "calculation": [Function], - "dateHistogramSubAggs": Object { - "bulk_deriv": Object { - "derivative": Object { - "buckets_path": "bulk_rejections", - "gap_policy": "skip", - "unit": "1s", - }, - }, - "bulk_rejections": Object { - "max": Object { - "field": "node_stats.thread_pool.bulk.rejected", - }, - }, - "index_deriv": Object { - "derivative": Object { - "buckets_path": "index_rejections", - "gap_policy": "skip", - "unit": "1s", - }, - }, - "index_rejections": Object { - "max": Object { - "field": "node_stats.thread_pool.index.rejected", - }, - }, - "write_deriv": Object { - "derivative": Object { - "buckets_path": "write_rejections", - "gap_policy": "skip", - "unit": "1s", - }, - }, - "write_rejections": Object { - "max": Object { - "field": "node_stats.thread_pool.write.rejected", - }, - }, - }, - "derivative": false, - "description": "Number of index, bulk, and write operations that have been rejected, which occurs when the queue is full. The bulk threadpool was renamed to write in 6.3, and the index threadpool is deprecated.", - "field": "node_stats.thread_pool.write.rejected", - "format": "0.[00]", - "label": "Write Rejections", + "derivative": true, + "description": "Number of search operations that have been rejected, which occurs when the queue is full.", + "field": "node_stats.thread_pool.search.rejected", + "format": "0,0.[00]", + "label": "Search Rejections", "metricAgg": "max", + "min": 0, "timestampField": "timestamp", - "title": "Indexing Threads", + "title": "Read Threads", "type": "node", "units": "", "uuidField": "source_node.uuid", }, - "node_index_time": Object { + "node_index_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of time spent on indexing operations.", @@ -3019,7 +2997,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "node_index_total": Object { + "node_index_total": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of indexing operations.", @@ -3033,7 +3011,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_jvm_gc_old_count": Object { + "node_jvm_gc_old_count": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Number of old Garbage Collections.", @@ -3047,7 +3025,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_jvm_gc_old_time": Object { + "node_jvm_gc_old_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Time spent performing old Garbage Collections.", @@ -3061,7 +3039,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "node_jvm_gc_young_count": Object { + "node_jvm_gc_young_count": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Number of young Garbage Collections.", @@ -3075,7 +3053,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_jvm_gc_young_time": Object { + "node_jvm_gc_young_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Time spent performing young Garbage Collections.", @@ -3089,7 +3067,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "node_jvm_mem_max_in_bytes": Object { + "node_jvm_mem_max_in_bytes": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap available to Elasticsearch running in the JVM.", @@ -3103,7 +3081,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_jvm_mem_percent": Object { + "node_jvm_mem_percent": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap used by Elasticsearch running in the JVM.", @@ -3117,7 +3095,7 @@ Object { "units": "%", "uuidField": "source_node.uuid", }, - "node_jvm_mem_used_in_bytes": Object { + "node_jvm_mem_used_in_bytes": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Total heap used by Elasticsearch running in the JVM.", @@ -3131,7 +3109,7 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_load_average": Object { + "node_load_average": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Load average over the last minute.", @@ -3145,7 +3123,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_query_latency": Object { + "node_query_latency": LatencyMetric { "aggs": Object { "event_time_in_millis": Object { "max": Object { @@ -3186,7 +3164,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "node_search_total": Object { + "node_search_total": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of search operations (per shard).", @@ -3200,7 +3178,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_segment_count": Object { + "node_segment_count": ElasticsearchMetric { "app": "elasticsearch", "derivative": false, "description": "Maximum segment count for primary and replica shards on this node.", @@ -3213,7 +3191,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_queued_bulk": Object { + "node_threads_queued_bulk": ThreadPoolQueueMetric { "app": "elasticsearch", "derivative": false, "description": "Number of bulk indexing operations waiting to be processed on this node. A single bulk request can create multiple bulk operations.", @@ -3227,7 +3205,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_queued_generic": Object { + "node_threads_queued_generic": ThreadPoolQueueMetric { "app": "elasticsearch", "derivative": false, "description": "Number of generic (internal) operations waiting to be processed on this node.", @@ -3241,7 +3219,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_queued_get": Object { + "node_threads_queued_get": ThreadPoolQueueMetric { "app": "elasticsearch", "derivative": false, "description": "Number of get operations waiting to be processed on this node.", @@ -3255,7 +3233,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_queued_index": Object { + "node_threads_queued_index": ThreadPoolQueueMetric { "app": "elasticsearch", "derivative": false, "description": "Number of non-bulk, index operations waiting to be processed on this node.", @@ -3269,7 +3247,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_queued_management": Object { + "node_threads_queued_management": ThreadPoolQueueMetric { "app": "elasticsearch", "derivative": false, "description": "Number of management (internal) operations waiting to be processed on this node.", @@ -3283,7 +3261,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_queued_search": Object { + "node_threads_queued_search": ThreadPoolQueueMetric { "app": "elasticsearch", "derivative": false, "description": "Number of search operations waiting to be processed on this node. A single search request can create multiple search operations.", @@ -3297,7 +3275,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_queued_watcher": Object { + "node_threads_queued_watcher": ThreadPoolQueueMetric { "app": "elasticsearch", "derivative": false, "description": "Number of Watcher operations waiting to be processed on this node.", @@ -3311,7 +3289,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_rejected_bulk": Object { + "node_threads_rejected_bulk": ThreadPoolRejectedMetric { "app": "elasticsearch", "derivative": true, "description": "Bulk rejections. These occur when the queue is full.", @@ -3325,7 +3303,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_rejected_generic": Object { + "node_threads_rejected_generic": ThreadPoolRejectedMetric { "app": "elasticsearch", "derivative": true, "description": "Generic (internal) rejections. These occur when the queue is full.", @@ -3339,7 +3317,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_rejected_get": Object { + "node_threads_rejected_get": ThreadPoolRejectedMetric { "app": "elasticsearch", "derivative": true, "description": "Get rejections. These occur when the queue is full.", @@ -3353,7 +3331,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_rejected_index": Object { + "node_threads_rejected_index": ThreadPoolRejectedMetric { "app": "elasticsearch", "derivative": true, "description": "Index rejections. These occur when the queue is full. You should look at bulk indexing.", @@ -3367,7 +3345,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_rejected_management": Object { + "node_threads_rejected_management": ThreadPoolRejectedMetric { "app": "elasticsearch", "derivative": true, "description": "Get (internal) rejections. These occur when the queue is full.", @@ -3381,7 +3359,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_rejected_search": Object { + "node_threads_rejected_search": ThreadPoolRejectedMetric { "app": "elasticsearch", "derivative": true, "description": "Search rejections. These occur when the queue is full. This can indicate over-sharding.", @@ -3395,7 +3373,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_threads_rejected_watcher": Object { + "node_threads_rejected_watcher": ThreadPoolRejectedMetric { "app": "elasticsearch", "derivative": true, "description": "Watch rejections. These occur when the queue is full. This can indicate stuck-Watches.", @@ -3409,7 +3387,7 @@ Object { "units": "", "uuidField": "source_node.uuid", }, - "node_throttle_index_time": Object { + "node_throttle_index_time": ElasticsearchMetric { "app": "elasticsearch", "derivative": true, "description": "Amount of time spent with index throttling, which indicates slow disks on a node.", @@ -3424,7 +3402,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "query_latency": Object { + "query_latency": LatencyMetric { "aggs": Object { "event_time_in_millis": Object { "max": Object { @@ -3464,7 +3442,7 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "search_request_rate": Object { + "search_request_rate": RequestRateMetric { "app": "elasticsearch", "derivative": true, "description": "Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!", diff --git a/x-pack/plugins/monitoring/server/lib/metrics/__test__/beats_cpu_utilization_calculation.test.js b/x-pack/plugins/monitoring/server/lib/metrics/beats/__test__/cpu_utilization_calculation.test.js similarity index 100% rename from x-pack/plugins/monitoring/server/lib/metrics/__test__/beats_cpu_utilization_calculation.test.js rename to x-pack/plugins/monitoring/server/lib/metrics/beats/__test__/cpu_utilization_calculation.test.js diff --git a/x-pack/plugins/monitoring/server/lib/metrics/beats/classes.js b/x-pack/plugins/monitoring/server/lib/metrics/beats/classes.js new file mode 100644 index 00000000000000..f7da44c050b380 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/beats/classes.js @@ -0,0 +1,156 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ClusterMetric, Metric } from '../classes'; +import { + SMALL_FLOAT, + LARGE_FLOAT, + LARGE_BYTES +} from '../../../../common/formatting'; +import { NORMALIZED_DERIVATIVE_UNIT } from '../../../../common/constants'; + +export class BeatsClusterMetric extends ClusterMetric { + constructor(opts) { + super({ + ...opts, + app: 'beats', + ...BeatsClusterMetric.getMetricFields() + }); + } + + static getMetricFields() { + return { + uuidField: 'beats_stats.beat.uuid', + timestampField: 'beats_stats.timestamp' + }; + } +} + +export class BeatsEventsRateClusterMetric extends BeatsClusterMetric { + constructor(opts) { + super({ + ...opts, + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '/s' + }); + + this.aggs = { + beats_uuids: { + terms: { + field: 'beats_stats.beat.uuid', + size: 10000 + }, + aggs: { + event_rate_per_beat: { + max: { + field: this.field + } + } + } + }, + event_rate: { + sum_bucket: { + buckets_path: 'beats_uuids>event_rate_per_beat', + gap_policy: 'skip' + } + }, + metric_deriv: { + derivative: { + buckets_path: 'event_rate', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + } + }; + } +} + +export class BeatsMetric extends Metric { + constructor(opts) { + super({ + ...opts, + app: 'beats', + ...BeatsMetric.getMetricFields() + }); + } + + static getMetricFields() { + return { + uuidField: 'beats_stats.beat.uuid', + timestampField: 'beats_stats.timestamp' + }; + } +} + +export class BeatsByteRateClusterMetric extends BeatsEventsRateClusterMetric { + constructor(opts) { + super({ + ...opts, + format: LARGE_BYTES + }); + } +} + +export class BeatsEventsRateMetric extends BeatsMetric { + constructor(opts) { + super({ + ...opts, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '/s', + derivative: true + }); + } +} + +export class BeatsByteRateMetric extends BeatsMetric { + constructor(opts) { + super({ + ...opts, + format: LARGE_BYTES, + metricAgg: 'max', + units: '/s', + derivative: true + }); + } +} + +export class BeatsCpuUtilizationMetric extends BeatsMetric { + constructor(opts) { + super({ + ...opts, + format: SMALL_FLOAT, + metricAgg: 'max', + units: '%', + derivative: true + }); + + /* + * Convert a counter of milliseconds of utilization time into a percentage of the bucket size + */ + this.calculation = ( + { metric_deriv: metricDeriv } = {}, + _key, + _metric, + bucketSizeInSeconds + ) => { + if (metricDeriv) { + const { normalized_value: metricDerivNormalizedValue } = metricDeriv; + const bucketSizeInMillis = bucketSizeInSeconds * 1000; + + if ( + metricDerivNormalizedValue >= 0 && + metricDerivNormalizedValue !== null + ) { + return metricDerivNormalizedValue / bucketSizeInMillis * 100; + } + } + return null; + }; + } +} diff --git a/x-pack/plugins/monitoring/server/lib/metrics/beats/metrics.js b/x-pack/plugins/monitoring/server/lib/metrics/beats/metrics.js new file mode 100644 index 00000000000000..4b61656c2c6d17 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/beats/metrics.js @@ -0,0 +1,252 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + BeatsEventsRateClusterMetric, + BeatsByteRateClusterMetric, + BeatsEventsRateMetric, + BeatsByteRateMetric, + BeatsCpuUtilizationMetric, + BeatsMetric +} from './classes'; +import { LARGE_FLOAT, LARGE_BYTES } from '../../../../common/formatting'; + +export const metrics = { + beat_cluster_pipeline_events_total_rate: new BeatsEventsRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.pipeline.events.total', + title: 'Events Rate', + label: 'Total', + description: 'All events newly created in the publishing pipeline' + }), + beat_cluster_output_events_total: new BeatsEventsRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.output.events.total', + title: 'Events Rate', + label: 'Emitted', + description: 'Events processed by the output (including retries)' + }), + beat_cluster_output_events_ack_rate: new BeatsEventsRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.output.events.acked', + title: 'Events Rate', + label: 'Acknowledged', + description: + 'Events acknowledged by the output (includes events dropped by the output)' + }), + beat_cluster_pipeline_events_emitted_rate: new BeatsEventsRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.pipeline.events.published', + title: 'Events Rate', + label: 'Queued', + description: 'Events added to the event pipeline queue' + }), + + beat_cluster_output_write_bytes_rate: new BeatsByteRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.output.write.bytes', + title: 'Throughput', + label: 'Bytes Sent', + description: + 'Bytes written to the output (consists of size of network headers and compressed payload)' + }), + beat_cluster_output_read_bytes_rate: new BeatsByteRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.output.read.bytes', + title: 'Throughput', + label: 'Bytes Received', + description: 'Bytes read in response from the output' + }), + + beat_cluster_pipeline_events_failed_rate: new BeatsEventsRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.pipeline.events.failed', + title: 'Fail Rates', + label: 'Failed in Pipeline', + description: + 'Failures that happened before event was added to the publishing pipeline (output was disabled or publisher client closed)' + }), + beat_cluster_pipeline_events_dropped_rate: new BeatsEventsRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.pipeline.events.dropped', + title: 'Fail Rates', + label: 'Dropped in Pipeline', + description: + 'Events that have been dropped after N retries (N = max_retries setting)' + }), + beat_cluster_output_events_dropped_rate: new BeatsEventsRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.output.events.dropped', + title: 'Fail Rates', + label: 'Dropped in Output', + description: + '(Fatal drop) Events dropped by the output as being "invalid." The output ' + + 'still acknowledges the event for the Beat to remove it from the queue.' + }), + beat_cluster_pipeline_events_retry_rate: new BeatsEventsRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.pipeline.events.retry', + title: 'Fail Rates', + label: 'Retry in Pipeline', + description: + 'Events in the pipeline that are trying again to be sent to the output' + }), + + beat_cluster_output_sending_errors: new BeatsEventsRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.output.write.errors', + title: 'Output Errors', + label: 'Sending', + description: 'Errors in writing the response from the output' + }), + beat_cluster_output_receiving_errors: new BeatsEventsRateClusterMetric({ + field: 'beats_stats.metrics.libbeat.output.read.errors', + title: 'Output Errors', + label: 'Receiving', + description: 'Errors in reading the response from the output' + }), + + /* + * Beat Detail + */ + + beat_pipeline_events_total_rate: new BeatsEventsRateMetric({ + field: 'beats_stats.metrics.libbeat.pipeline.events.total', + title: 'Events Rate', + label: 'New', + description: 'New events sent to the publishing pipeline' + }), + beat_output_events_total: new BeatsEventsRateMetric({ + field: 'beats_stats.metrics.libbeat.output.events.total', + title: 'Events Rate', + label: 'Emitted', + description: 'Events processed by the output (including retries)' + }), + beat_output_events_ack_rate: new BeatsEventsRateMetric({ + field: 'beats_stats.metrics.libbeat.output.events.acked', + title: 'Events Rate', + label: 'Acknowledged', + description: + 'Events acknowledged by the output (includes events dropped by the output)' + }), + beat_pipeline_events_emitted_rate: new BeatsEventsRateMetric({ + field: 'beats_stats.metrics.libbeat.pipeline.events.published', + title: 'Events Rate', + label: 'Queued', + description: 'Events added to the event pipeline queue' + }), + + beat_pipeline_events_failed_rate: new BeatsEventsRateMetric({ + field: 'beats_stats.metrics.libbeat.pipeline.events.failed', + title: 'Fail Rates', + label: 'Failed in Pipeline', + description: + 'Failures that happened before event was added to the publishing pipeline (output was disabled or publisher client closed)' + }), + beat_pipeline_events_dropped_rate: new BeatsEventsRateMetric({ + field: 'beats_stats.metrics.libbeat.pipeline.events.dropped', + title: 'Fail Rates', + label: 'Dropped in Pipeline', + description: + 'Events that have been dropped after N retries (N = max_retries setting)' + }), + beat_output_events_dropped_rate: new BeatsEventsRateMetric({ + field: 'beats_stats.metrics.libbeat.output.events.dropped', + title: 'Fail Rates', + label: 'Dropped in Output', + description: + '(Fatal drop) Events dropped by the output as being "invalid." The output ' + + 'still acknowledges the event for the Beat to remove it from the queue.' + }), + beat_pipeline_events_retry_rate: new BeatsEventsRateMetric({ + field: 'beats_stats.metrics.libbeat.pipeline.events.retry', + title: 'Fail Rates', + label: 'Retry in Pipeline', + description: + 'Events in the pipeline that are trying again to be sent to the output' + }), + + beat_bytes_written: new BeatsByteRateMetric({ + field: 'beats_stats.metrics.libbeat.output.write.bytes', + title: 'Throughput', + label: 'Bytes Sent', + description: + 'Bytes written to the output (consists of size of network headers and compressed payload)' + }), + beat_output_write_bytes_rate: new BeatsByteRateMetric({ + field: 'beats_stats.metrics.libbeat.output.read.bytes', + title: 'Throughput', + label: 'Bytes Received', + description: 'Bytes read in response from the output' + }), + + beat_output_sending_errors: new BeatsEventsRateMetric({ + field: 'beats_stats.metrics.libbeat.output.write.errors', + title: 'Output Errors', + label: 'Sending', + description: 'Errors in writing the response from the output' + }), + beat_output_receiving_errors: new BeatsEventsRateMetric({ + field: 'beats_stats.metrics.libbeat.output.read.errors', + title: 'Output Errors', + label: 'Receiving', + description: 'Errors in reading the response from the output' + }), + + beat_mem_alloc: new BeatsMetric({ + field: 'beats_stats.metrics.beat.memstats.memory_alloc', + label: 'Active', + title: 'Memory', + description: 'Private memory in active use by the Beat', + format: LARGE_BYTES, + metricAgg: 'max', + units: 'B' + }), + beat_mem_rss: new BeatsMetric({ + field: 'beats_stats.metrics.beat.memstats.rss', + label: 'Process Total', + title: 'Memory', + description: 'Resident set size of memory reserved by the Beat from the OS', + format: LARGE_BYTES, + metricAgg: 'max', + units: 'B' + }), + beat_mem_gc_next: new BeatsMetric({ + field: 'beats_stats.metrics.beat.memstats.gc_next', + label: 'GC Next', + title: 'Memory', + description: + 'Limit of allocated memory at which garbage collection will occur', + format: LARGE_BYTES, + metricAgg: 'max', + units: 'B' + }), + + beat_cpu_utilization: new BeatsCpuUtilizationMetric({ + title: 'CPU Utilization', + label: 'Total', + description: + 'Percentage of CPU time spent executing (user+kernel mode) for the Beat process', + field: 'beats_stats.metrics.beat.cpu.total.value' + }), + + beat_system_os_load_1: new BeatsMetric({ + field: 'beats_stats.metrics.system.load.1', + label: '1m', + title: 'System Load', + description: 'Load average over the last 1 minute', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + beat_system_os_load_5: new BeatsMetric({ + field: 'beats_stats.metrics.system.load.5', + label: '5m', + title: 'System Load', + description: 'Load average over the last 5 minutes', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + beat_system_os_load_15: new BeatsMetric({ + field: 'beats_stats.metrics.system.load.15', + label: '15m', + title: 'System Load', + description: 'Load average over the last 15 minutes', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }) +}; diff --git a/x-pack/plugins/monitoring/server/lib/metrics/classes.js b/x-pack/plugins/monitoring/server/lib/metrics/classes.js deleted file mode 100644 index c84d8ba169de3b..00000000000000 --- a/x-pack/plugins/monitoring/server/lib/metrics/classes.js +++ /dev/null @@ -1,974 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import _ from 'lodash'; -import { MissingRequiredError } from '../error_missing_required'; -import { - LARGE_FLOAT, - SMALL_FLOAT, - SMALL_BYTES, - LARGE_BYTES -} from '../../../common/formatting'; -import { NORMALIZED_DERIVATIVE_UNIT } from '../../../common/constants'; - -/** - * Calculate the latency, if any, for the {@code eventTimeInMillis} and {@code totalEvents}. - * - * @param {Number} eventTimeInMillis {@code null} if unknown. Time spent on the events - * @param {Number} totalEvents {@code null} if unknown. Total number of events - * @return {Number} {@code null} if unknown. Window size of the events in seconds - */ -function calculateLatency(timeInMillis, totalEvents) { - if (timeInMillis === null || totalEvents === null) { - return null; - } else if (timeInMillis < 0 || totalEvents < 0) { - // Negative values indicate blips in the data (e.g., restarting a node) that we do not want to misrepresent - return null; - } else if (totalEvents === 0) { - return 0; - } - - return timeInMillis / totalEvents; -} - - -export class Metric { - constructor(opts) { - const props = { - derivative: false - }; - - const requireds = { - field: opts.field, - label: opts.label, - description: opts.description, - format: opts.format, - units: opts.units, - timestampField: opts.timestampField - }; - this.checkRequiredParams(requireds); - _.assign(this, _.defaults(opts, props)); - } - - checkRequiredParams(requireds) { - const undefKey = _.findKey(requireds, _.isUndefined); - if (undefKey) { - console.log(`Missing required field: [${undefKey}]`); - throw new MissingRequiredError(undefKey); - } - } - - toPlainObject() { - return _.toPlainObject(this); - } -} - -export class ElasticsearchMetric extends Metric { - constructor(opts) { - super({ - ...opts, - app: 'elasticsearch', - uuidField: 'source_node.uuid', - timestampField: 'timestamp' - }); - - this.checkRequiredParams({ type: opts.type }); - } - - // helper method - static getMetricFields() { - return { - uuidField: 'source_node.uuid', - timestampField: 'timestamp' - }; - } -} - -export class KibanaEventsRateClusterMetric extends Metric { - constructor(opts) { - super({ - ...opts, - app: 'kibana', - uuidField: 'cluster_uuid', - timestampField: 'kibana_stats.timestamp', - metricAgg: 'max' - }); - - this.aggs = { - kibana_uuids: { - terms: { - field: 'kibana_stats.kibana.uuid', - size: 1000 - }, - aggs: { - event_rate_per_instance: { - max: { - field: this.field - } - } - } - }, - event_rate: { - sum_bucket: { - buckets_path: 'kibana_uuids>event_rate_per_instance', - gap_policy: 'skip' - } - }, - metric_deriv: { - derivative: { - buckets_path: 'event_rate', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - } - }; - } - - // helper method - static getMetricFields() { - return { - uuidField: 'cluster_uuid', - timestampField: 'kibana_stats.timestamp' - }; - } -} - -export class KibanaMetric extends Metric { - constructor(opts) { - super({ - ...opts, - app: 'kibana', - uuidField: 'kibana_stats.kibana.uuid', - timestampField: 'kibana_stats.timestamp' - }); - } -} - -export class LatencyMetric extends ElasticsearchMetric { - constructor({ metric, fieldSource, ...opts }) { - super({ - ...opts, - format: LARGE_FLOAT, - metricAgg: 'sum', // NOTE: this is used for a pointless aggregation - units: 'ms' - }); - - this.checkRequiredParams({ - metric, - fieldSource - }); - - let metricField; - if (metric === 'index') { - metricField = 'indexing.index'; - } else if (metric === 'query') { - metricField = 'search.query'; - } else { - throw new Error('Latency metric param must be a string equal to `index` or `query`'); - } - - const timeInMillisField = `${fieldSource}.${metricField}_time_in_millis`; - const eventTotalField = `${fieldSource}.${metricField}_total`; - - this.aggs = { - event_time_in_millis: { - max: { field: timeInMillisField } - }, - event_total: { - max: { field: eventTotalField } - }, - event_time_in_millis_deriv: { - derivative: { - buckets_path: 'event_time_in_millis', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT - } - }, - event_total_deriv: { - derivative: { - buckets_path: 'event_total', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT - } - } - }; - - this.calculation = (bucket, _key, _metric, _bucketSizeInSeconds) => { - const timeInMillisDeriv = _.get(bucket, 'event_time_in_millis_deriv.normalized_value', null); - const totalEventsDeriv = _.get(bucket, 'event_total_deriv.normalized_value', null); - return calculateLatency(timeInMillisDeriv, totalEventsDeriv); - }; - } -} - -export class QuotaMetric extends Metric { - constructor(opts) { - super({ - ...opts, - format: LARGE_FLOAT, - metricAgg: 'max', // makes an average metric of `this.field`, which is the "actual cpu utilization" - derivative: true, - units: '%' - }); - - this.aggs = { - usage: { - max: { field: `${this.fieldSource}.${this.usageField}` } - }, - periods: { - max: { field: `${this.fieldSource}.${this.periodsField}` } - }, - quota: { - // Use min for this value. Basically equivalient to max, but picks -1 - // as the value if quota is disabled in one of the docs, which affects - // the logic by routing to the non-quota scenario - min: { - field: `${this.fieldSource}.${this.quotaField}` - } - }, - usage_deriv: { - derivative: { - buckets_path: 'usage', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - }, - periods_deriv: { - derivative: { - buckets_path: 'periods', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - }, - }; - - this.calculation = (bucket) => { - - const quota = _.get(bucket, 'quota.value'); - const deltaUsageDerivNormalizedValue = _.get(bucket, 'usage_deriv.normalized_value'); - const periodsDerivNormalizedValue = _.get(bucket, 'periods_deriv.normalized_value'); - - if (deltaUsageDerivNormalizedValue && periodsDerivNormalizedValue && quota > 0) { - // if throttling is configured - const factor = deltaUsageDerivNormalizedValue / (periodsDerivNormalizedValue * quota * 1000); // convert quota from microseconds to nanoseconds by multiplying 1000 - return factor * 100; // convert factor to percentage - - } - // if throttling is NOT configured, show nothing. The user should see that something is not configured correctly - return null; - - }; - } - -} - -export class RequestRateMetric extends ElasticsearchMetric { - - constructor(opts) { - super({ - ...opts, - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '/s' - }); - } - -} - -export class ThreadPoolQueueMetric extends ElasticsearchMetric { - - constructor(opts) { - super({ - ...opts, - title: 'Thread Queue', - type: 'node', - format: SMALL_FLOAT, - metricAgg: 'max', - units: '' - }); - } - -} - -export class ThreadPoolRejectedMetric extends ElasticsearchMetric { - - constructor(opts) { - super({ - ...opts, - title: 'Thread Rejections', - type: 'node', - derivative: true, - format: SMALL_FLOAT, - metricAgg: 'max', - units: '' - }); - } - -} - -export class WriteThreadPoolQueueMetric extends ElasticsearchMetric { - - constructor(opts) { - super({ - ...opts, - field: 'node_stats.thread_pool.write.queue', // in 7.0, we can only check for this threadpool - type: 'node', - format: SMALL_FLOAT, - metricAgg: 'max', - units: '' - }); - - this.dateHistogramSubAggs = { - index: { - max: { field: 'node_stats.thread_pool.index.queue' } - }, - bulk: { - max: { field: 'node_stats.thread_pool.bulk.queue' } - }, - write: { - max: { field: 'node_stats.thread_pool.write.queue' } - }, - }; - - this.calculation = (bucket) => { - const index = _.get(bucket, 'index.value', null); - const bulk = _.get(bucket, 'bulk.value', null); - const write = _.get(bucket, 'write.value', null); - - if (index !== null || bulk !== null || write !== null) { - return (index || 0) + (bulk || 0) + (write || 0); - } - - // ignore the data if none of them exist - return null; - }; - } - -} - -export class WriteThreadPoolRejectedMetric extends ElasticsearchMetric { - - constructor(opts) { - super({ - ...opts, - field: 'node_stats.thread_pool.write.rejected', // in 7.0, we can only check for this threadpool - type: 'node', - format: SMALL_FLOAT, - metricAgg: 'max', - units: '' - }); - - this.dateHistogramSubAggs = { - index_rejections: { - max: { field: 'node_stats.thread_pool.index.rejected' } - }, - bulk_rejections: { - max: { field: 'node_stats.thread_pool.bulk.rejected' } - }, - write_rejections: { - max: { field: 'node_stats.thread_pool.write.rejected' } - }, - index_deriv: { - derivative: { - buckets_path: 'index_rejections', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - }, - bulk_deriv: { - derivative: { - buckets_path: 'bulk_rejections', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - }, - write_deriv: { - derivative: { - buckets_path: 'write_rejections', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - }, - }; - - this.calculation = (bucket) => { - const index = _.get(bucket, 'index_deriv.normalized_value', null); - const bulk = _.get(bucket, 'bulk_deriv.normalized_value', null); - const write = _.get(bucket, 'write_deriv.normalized_value', null); - - if (index !== null || bulk !== null || write !== null) { - const valueOrZero = value => value < 0 ? 0 : (value || 0); - - return valueOrZero(index) + valueOrZero(bulk) + valueOrZero(write); - } - - // ignore the data if none of them exist - return null; - }; - } - -} - -/** - * A generic {@code class} for collecting Index Memory metrics. - * - * @see IndicesMemoryMetric - * @see NodeIndexMemoryMetric - * @see SingleIndexMemoryMetric - */ -export class IndexMemoryMetric extends ElasticsearchMetric { - - constructor(opts) { - super({ - title: 'Index Memory', - ...opts, - format: SMALL_BYTES, - metricAgg: 'max', - units: 'B' - }); - } - -} - -export class NodeIndexMemoryMetric extends IndexMemoryMetric { - - constructor(opts) { - super({ - ...opts, - type: 'node' - }); - - // override the field set by the super constructor - this.field = 'node_stats.indices.segments.' + opts.field; - } - -} - -export class IndicesMemoryMetric extends IndexMemoryMetric { - - constructor(opts) { - super({ - ...opts, - type: 'cluster' - }); - - // override the field set by the super constructor - this.field = 'index_stats.total.segments.' + opts.field; - } - -} - -export class SingleIndexMemoryMetric extends IndexMemoryMetric { - - constructor(opts) { - super({ - ...opts, - type: 'index' - }); - - // override the field set by the super constructor - this.field = 'index_stats.total.segments.' + opts.field; - } - -} - -export class LogstashMetric extends Metric { - - constructor(opts) { - super({ - ...opts, - app: 'logstash', - uuidField: 'logstash_stats.logstash.uuid', - timestampField: 'logstash_stats.timestamp' - }); - } - -} - -export class LogstashClusterMetric extends Metric { - - constructor(opts) { - super({ - ...opts, - app: 'logstash', - timestampField: 'logstash_stats.timestamp' - }); - } - - // helper method - static getMetricFields() { - return { - timestampField: 'logstash_stats.timestamp' - }; - } -} - -export class LogstashEventsLatencyMetric extends LogstashMetric { - - constructor(opts) { - super({ - ...opts, - format: LARGE_FLOAT, - metricAgg: 'sum', - units: 'ms' - }); - - this.aggs = { - events_time_in_millis: { - max: { field: 'logstash_stats.events.duration_in_millis' } - }, - events_total: { - max: { field: 'logstash_stats.events.out' } - }, - events_time_in_millis_deriv: { - derivative: { - buckets_path: 'events_time_in_millis', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - }, - events_total_deriv: { - derivative: { - buckets_path: 'events_total', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - } - }; - - this.calculation = (bucket, _key, _metric, _bucketSizeInSeconds) => { - const timeInMillisDeriv = _.get(bucket, 'events_time_in_millis_deriv.normalized_value', null); - const totalEventsDeriv = _.get(bucket, 'events_total_deriv.normalized_value', null); - - return calculateLatency(timeInMillisDeriv, totalEventsDeriv); - }; - } - -} - -export class LogstashEventsLatencyClusterMetric extends LogstashClusterMetric { - - constructor(opts) { - super({ - ...opts, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms' - }); - - this.aggs = { - logstash_uuids: { - terms: { - field: 'logstash_stats.logstash.uuid', - size: 1000 - }, - aggs: { - events_time_in_millis_per_node: { - max: { - field: 'logstash_stats.events.duration_in_millis' - } - }, - events_total_per_node: { - max: { - field: 'logstash_stats.events.out' - } - } - } - }, - events_time_in_millis: { - sum_bucket: { - buckets_path: 'logstash_uuids>events_time_in_millis_per_node', - gap_policy: 'skip' - } - }, - events_total: { - sum_bucket: { - buckets_path: 'logstash_uuids>events_total_per_node', - gap_policy: 'skip' - } - }, - events_time_in_millis_deriv: { - derivative: { - buckets_path: 'events_time_in_millis', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - }, - events_total_deriv: { - derivative: { - buckets_path: 'events_total', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - } - }; - - this.calculation = (bucket, _key, _metric, _bucketSizeInSeconds) => { - const timeInMillisDeriv = _.get(bucket, 'events_time_in_millis_deriv.normalized_value', null); - const totalEventsDeriv = _.get(bucket, 'events_total_deriv.normalized_value', null); - - return calculateLatency(timeInMillisDeriv, totalEventsDeriv); - }; - } - -} - -export class LogstashEventsRateMetric extends LogstashMetric { - - constructor(opts) { - super({ - ...opts, - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '/s' - }); - } - -} - -export class LogstashEventsRateClusterMetric extends LogstashClusterMetric { - - constructor(opts) { - super({ - ...opts, - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '/s' - }); - - this.aggs = { - logstash_uuids: { - terms: { - field: 'logstash_stats.logstash.uuid', - size: 1000 - }, - aggs: { - event_rate_per_node: { - max: { - field: this.field - } - } - } - }, - event_rate: { - sum_bucket: { - buckets_path: 'logstash_uuids>event_rate_per_node', - gap_policy: 'skip' - } - }, - metric_deriv: { - derivative: { - buckets_path: 'event_rate', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - } - }; - } - -} - -export class LogstashPipelineQueueSizeMetric extends LogstashMetric { - constructor(opts) { - super({ ...opts }); - - this.dateHistogramSubAggs = { - pipelines: { - nested: { - path: 'logstash_stats.pipelines' - }, - aggs: { - pipeline_by_id: { - terms: { - field: 'logstash_stats.pipelines.id', - size: 1000 - }, - aggs: { - queue_size_field: { - max: { - field: this.field - } - } - } - }, - total_queue_size_for_node: { - sum_bucket: { - buckets_path: 'pipeline_by_id>queue_size_field' - } - } - } - } - }; - - this.calculation = bucket => _.get(bucket, 'pipelines.total_queue_size_for_node.value'); - } -} - -export class LogstashPipelineThroughputMetric extends LogstashMetric { - constructor(opts) { - super({ - ...opts, - derivative: false - }); - - this.dateHistogramSubAggs = { - pipelines_nested: { - nested: { - path: 'logstash_stats.pipelines' - }, - aggs: { - by_pipeline_id: { - terms: { - field: 'logstash_stats.pipelines.id', - size: 1000 - }, - aggs: { - throughput: { - sum_bucket: { - buckets_path: 'by_pipeline_hash>throughput' - } - }, - by_pipeline_hash: { - terms: { - field: 'logstash_stats.pipelines.hash', - size: 1000 - }, - aggs: { - throughput: { - sum_bucket: { - buckets_path: 'by_ephemeral_id>throughput' - } - }, - by_ephemeral_id: { - terms: { - field: 'logstash_stats.pipelines.ephemeral_id', - size: 1000 - }, - aggs: { - events_stats: { - stats: { - field: this.field - } - }, - throughput: { - bucket_script: { - script: 'params.max - params.min', - buckets_path: { - min: 'events_stats.min', - max: 'events_stats.max' - } - } - } - } - } - } - } - } - } - } - } - }; - - this.calculation = (bucket, _key, _metric, bucketSizeInSeconds) => { - const pipelineThroughputs = {}; - const pipelineBuckets = _.get(bucket, 'pipelines_nested.by_pipeline_id.buckets', []); - pipelineBuckets.forEach(pipelineBucket => { - pipelineThroughputs[pipelineBucket.key] = - bucketSizeInSeconds ? _.get(pipelineBucket, 'throughput.value') / bucketSizeInSeconds : undefined; - }); - - return pipelineThroughputs; - }; - } -} - -export class LogstashPipelineNodeCountMetric extends LogstashMetric { - constructor(opts) { - super({ - ...opts, - derivative: false - }); - - this.dateHistogramSubAggs = { - pipelines_nested: { - nested: { - path: 'logstash_stats.pipelines' - }, - aggs: { - by_pipeline_id: { - terms: { - field: 'logstash_stats.pipelines.id', - size: 1000 - }, - aggs: { - to_root: { - reverse_nested: {}, - aggs: { - node_count: { - cardinality: { - field: this.field - } - } - } - } - } - } - } - } - }; - - this.calculation = (bucket) => { - const pipelineNodesCounts = {}; - const pipelineBuckets = _.get(bucket, 'pipelines_nested.by_pipeline_id.buckets', []); - pipelineBuckets.forEach(pipelineBucket => { - pipelineNodesCounts[pipelineBucket.key] = _.get(pipelineBucket, 'to_root.node_count.value'); - }); - - return pipelineNodesCounts; - }; - } -} - -export class BeatsClusterMetric extends Metric { - constructor(opts) { - super({ - ...opts, - app: 'beats', - timestampField: 'beats_stats.timestamp', - uuidField: 'cluster_uuid' - }); - } - - // helper method - static getMetricFields() { - return { - timestampField: 'beats_stats.timestamp' - }; - } -} - -export class BeatsEventsRateClusterMetric extends BeatsClusterMetric { - constructor(opts) { - super({ - ...opts, - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '/s' - }); - - this.aggs = { - beats_uuids: { - terms: { - field: 'beats_stats.beat.uuid', - size: 10000 - }, - aggs: { - event_rate_per_beat: { - max: { - field: this.field - } - } - } - }, - event_rate: { - sum_bucket: { - buckets_path: 'beats_uuids>event_rate_per_beat', - gap_policy: 'skip' - } - }, - metric_deriv: { - derivative: { - buckets_path: 'event_rate', - gap_policy: 'skip', - unit: NORMALIZED_DERIVATIVE_UNIT, - } - } - }; - } -} - -export class BeatsByteRateClusterMetric extends BeatsEventsRateClusterMetric { - constructor(opts) { - super({ - ...opts, - format: LARGE_BYTES - }); - } -} - -export class BeatsMetric extends Metric { - constructor(opts) { - super({ - ...opts, - app: 'beats', - uuidField: 'cluster_uuid', - timestampField: 'beats_stats.timestamp' - }); - } - - // helper method - static getMetricFields() { - return { - uuidField: 'cluster_uuid', - timestampField: 'beats_stats.timestamp' - }; - } -} - -export class BeatsEventsRateMetric extends BeatsMetric { - constructor(opts) { - super({ - ...opts, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '/s', - derivative: true - }); - } -} - -export class BeatsByteRateMetric extends BeatsMetric { - constructor(opts) { - super({ - ...opts, - format: LARGE_BYTES, - metricAgg: 'max', - units: '/s', - derivative: true - }); - } -} - -export class BeatsCpuUtilizationMetric extends BeatsMetric { - constructor(opts) { - super({ - ...opts, - format: SMALL_FLOAT, - metricAgg: 'max', - units: '%', - derivative: true - }); - - /* - * Convert a counter of milliseconds of utilization time into a percentage of the bucket size - */ - this.calculation = ({ metric_deriv: metricDeriv } = {}, _key, _metric, bucketSizeInSeconds) => { - if (metricDeriv) { - const { normalized_value: metricDerivNormalizedValue } = metricDeriv; - const bucketSizeInMillis = bucketSizeInSeconds * 1000; - - if (metricDerivNormalizedValue >= 0 && metricDerivNormalizedValue !== null) { - return metricDerivNormalizedValue / bucketSizeInMillis * 100; - } - } - return null; - }; - } -} diff --git a/x-pack/plugins/monitoring/server/lib/metrics/classes/__test__/latency_metric_calculation.test.js b/x-pack/plugins/monitoring/server/lib/metrics/classes/__test__/latency_metric_calculation.test.js new file mode 100644 index 00000000000000..9bacabe4b84bed --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/classes/__test__/latency_metric_calculation.test.js @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Metric } from '../'; + +describe('Latency Metric Calculation', () => { + it('should return null if any operands are null', () => { + const timeInMillis = null; + const totalEvents = 44; + expect(Metric.calculateLatency(timeInMillis, totalEvents)).toBe(null); + }); + + it('should return null if any operands are negative', () => { + const timeInMillis = -200; + const totalEvents = -44; + expect(Metric.calculateLatency(timeInMillis, totalEvents)).toBe(null); + }); + + it('should return 0 if there were no events in the bucket', () => { + const timeInMillis = 200; + const totalEvents = 0; + expect(Metric.calculateLatency(timeInMillis, totalEvents)).toBe(0); + }); + + it('should divide the time by the number of events for latency calculation', () => { + const timeInMillis = 200; + const totalEvents = 12; + expect(Metric.calculateLatency(timeInMillis, totalEvents)).toBeCloseTo(16.666666666666668); + }); +}); + diff --git a/x-pack/plugins/monitoring/server/lib/metrics/__test__/quota_metric_calculation.test.js b/x-pack/plugins/monitoring/server/lib/metrics/classes/__test__/quota_metric_calculation.test.js similarity index 98% rename from x-pack/plugins/monitoring/server/lib/metrics/__test__/quota_metric_calculation.test.js rename to x-pack/plugins/monitoring/server/lib/metrics/classes/__test__/quota_metric_calculation.test.js index 43f109353f53d0..823886f215dc98 100644 --- a/x-pack/plugins/monitoring/server/lib/metrics/__test__/quota_metric_calculation.test.js +++ b/x-pack/plugins/monitoring/server/lib/metrics/classes/__test__/quota_metric_calculation.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { QuotaMetric } from '..'; +import { QuotaMetric } from '../'; describe('Quota Metric Calculation', () => { it('When bucket is invalid, returns undefined', () => { diff --git a/x-pack/plugins/monitoring/server/lib/metrics/classes/cluster_metric.js b/x-pack/plugins/monitoring/server/lib/metrics/classes/cluster_metric.js new file mode 100644 index 00000000000000..efc350862b1fcd --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/classes/cluster_metric.js @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Metric } from './metric'; + +export class ClusterMetric extends Metric { + constructor(opts) { + super({ + ...opts, + uuidField: 'cluster_uuid' + }); + } +} diff --git a/x-pack/plugins/monitoring/server/lib/metrics/classes/index.js b/x-pack/plugins/monitoring/server/lib/metrics/classes/index.js new file mode 100644 index 00000000000000..af70a9d4aff21f --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/classes/index.js @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { Metric } from './metric'; +export { ClusterMetric } from './cluster_metric'; +export { QuotaMetric } from './quota_metric'; diff --git a/x-pack/plugins/monitoring/server/lib/metrics/classes/metric.js b/x-pack/plugins/monitoring/server/lib/metrics/classes/metric.js new file mode 100644 index 00000000000000..44d02689b867cf --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/classes/metric.js @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import { MissingRequiredError } from '../../error_missing_required'; + +export class Metric { + constructor(opts) { + const props = { + derivative: false + }; + + const requireds = { + field: opts.field, + label: opts.label, + description: opts.description, + format: opts.format, + units: opts.units, + timestampField: opts.timestampField + }; + this.checkRequiredParams(requireds); + _.assign(this, _.defaults(opts, props)); + } + + checkRequiredParams(requireds) { + const undefKey = _.findKey(requireds, _.isUndefined); + if (undefKey) { + console.log(`Missing required field: [${undefKey}]`); + throw new MissingRequiredError(undefKey); + } + } + + serialize() { + // some fields exposed for debugging through HTML comment text + const pickFields = [ + 'app', + 'field', + 'metricAgg', + 'label', + 'title', + 'description', + 'units', + 'format' + ]; + + const metric = Object.create(this); + return { + ..._.pick(metric, pickFields), + hasCalculation: Boolean(metric.calculation), + isDerivative: metric.derivative + }; + } + + static calculateLatency(timeInMillis, totalEvents) { + if (timeInMillis === null || totalEvents === null) { + return null; + } else if (timeInMillis < 0 || totalEvents < 0) { + // Negative values indicate blips in the data (e.g., restarting a node) that we do not want to misrepresent + return null; + } else if (totalEvents === 0) { + return 0; + } + + return timeInMillis / totalEvents; + } +} + + diff --git a/x-pack/plugins/monitoring/server/lib/metrics/classes/quota_metric.js b/x-pack/plugins/monitoring/server/lib/metrics/classes/quota_metric.js new file mode 100644 index 00000000000000..e791f7bb1ddfea --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/classes/quota_metric.js @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get } from 'lodash'; +import { Metric } from './metric'; +import { LARGE_FLOAT } from '../../../../common/formatting'; +import { NORMALIZED_DERIVATIVE_UNIT } from '../../../../common/constants'; + +export class QuotaMetric extends Metric { + constructor(opts) { + super({ + ...opts, + format: LARGE_FLOAT, + metricAgg: 'max', // makes an average metric of `this.field`, which is the "actual cpu utilization" + derivative: true, + units: '%' + }); + + this.aggs = { + usage: { + max: { field: `${this.fieldSource}.${this.usageField}` } + }, + periods: { + max: { field: `${this.fieldSource}.${this.periodsField}` } + }, + quota: { + // Use min for this value. Basically equivalient to max, but picks -1 + // as the value if quota is disabled in one of the docs, which affects + // the logic by routing to the non-quota scenario + min: { + field: `${this.fieldSource}.${this.quotaField}` + } + }, + usage_deriv: { + derivative: { + buckets_path: 'usage', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + }, + periods_deriv: { + derivative: { + buckets_path: 'periods', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + } + }; + + this.calculation = bucket => { + const quota = get(bucket, 'quota.value'); + const deltaUsageDerivNormalizedValue = get( + bucket, + 'usage_deriv.normalized_value' + ); + const periodsDerivNormalizedValue = get( + bucket, + 'periods_deriv.normalized_value' + ); + + if ( + deltaUsageDerivNormalizedValue && + periodsDerivNormalizedValue && + quota > 0 + ) { + // if throttling is configured + const factor = + deltaUsageDerivNormalizedValue / + (periodsDerivNormalizedValue * quota * 1000); // convert quota from microseconds to nanoseconds by multiplying 1000 + return factor * 100; // convert factor to percentage + } + // if throttling is NOT configured, show nothing. The user should see that something is not configured correctly + return null; + }; + } +} diff --git a/x-pack/plugins/monitoring/server/lib/metrics/__test__/latency_metric_calculation.test.js b/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/__test__/latency_calculation.test.js similarity index 97% rename from x-pack/plugins/monitoring/server/lib/metrics/__test__/latency_metric_calculation.test.js rename to x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/__test__/latency_calculation.test.js index 70c55b2eaa76c3..dfce27370502a3 100644 --- a/x-pack/plugins/monitoring/server/lib/metrics/__test__/latency_metric_calculation.test.js +++ b/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/__test__/latency_calculation.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { LatencyMetric } from '../'; +import { LatencyMetric } from '../classes'; describe('LatencyMetric for Query/Index Metric derivatives', () => { diff --git a/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/classes.js b/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/classes.js new file mode 100644 index 00000000000000..8fb8a6cc9652bb --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/classes.js @@ -0,0 +1,196 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import { Metric } from '../classes'; +import { + LARGE_FLOAT, + SMALL_FLOAT, + SMALL_BYTES +} from '../../../../common/formatting'; +import { NORMALIZED_DERIVATIVE_UNIT } from '../../../../common/constants'; + +export class ElasticsearchMetric extends Metric { + constructor(opts) { + super({ + ...opts, + app: 'elasticsearch', + uuidField: 'source_node.uuid', + timestampField: 'timestamp' + }); + + this.checkRequiredParams({ type: opts.type }); + } + + static getMetricFields() { + return { + uuidField: 'source_node.uuid', // ??? + timestampField: 'timestamp' + }; + } +} + +export class LatencyMetric extends ElasticsearchMetric { + constructor({ metric, fieldSource, ...opts }) { + super({ + ...opts, + format: LARGE_FLOAT, + metricAgg: 'sum', // NOTE: this is used for a pointless aggregation + units: 'ms' + }); + + this.checkRequiredParams({ + metric, + fieldSource + }); + + let metricField; + if (metric === 'index') { + metricField = 'indexing.index'; + } else if (metric === 'query') { + metricField = 'search.query'; + } else { + throw new Error( + 'Latency metric param must be a string equal to `index` or `query`' + ); + } + + const timeInMillisField = `${fieldSource}.${metricField}_time_in_millis`; + const eventTotalField = `${fieldSource}.${metricField}_total`; + + this.aggs = { + event_time_in_millis: { + max: { field: timeInMillisField } + }, + event_total: { + max: { field: eventTotalField } + }, + event_time_in_millis_deriv: { + derivative: { + buckets_path: 'event_time_in_millis', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + }, + event_total_deriv: { + derivative: { + buckets_path: 'event_total', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + } + }; + + this.calculation = (bucket, _key, _metric, _bucketSizeInSeconds) => { + const timeInMillisDeriv = _.get( + bucket, + 'event_time_in_millis_deriv.normalized_value', + null + ); + const totalEventsDeriv = _.get( + bucket, + 'event_total_deriv.normalized_value', + null + ); + + return Metric.calculateLatency(timeInMillisDeriv, totalEventsDeriv); + }; + } +} + +export class RequestRateMetric extends ElasticsearchMetric { + constructor(opts) { + super({ + ...opts, + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '/s' + }); + } +} + +export class ThreadPoolQueueMetric extends ElasticsearchMetric { + constructor(opts) { + super({ + ...opts, + title: 'Thread Queue', + type: 'node', + format: SMALL_FLOAT, + metricAgg: 'max', + units: '' + }); + } +} + +export class ThreadPoolRejectedMetric extends ElasticsearchMetric { + constructor(opts) { + super({ + ...opts, + title: 'Thread Rejections', + type: 'node', + derivative: true, + format: SMALL_FLOAT, + metricAgg: 'max', + units: '' + }); + } +} + +/** + * A generic {@code class} for collecting Index Memory metrics. + * + * @see IndicesMemoryMetric + * @see NodeIndexMemoryMetric + * @see SingleIndexMemoryMetric + */ +export class IndexMemoryMetric extends ElasticsearchMetric { + constructor(opts) { + super({ + title: 'Index Memory', + ...opts, + format: SMALL_BYTES, + metricAgg: 'max', + units: 'B' + }); + } +} + +export class NodeIndexMemoryMetric extends IndexMemoryMetric { + constructor(opts) { + super({ + ...opts, + type: 'node' + }); + + // override the field set by the super constructor + this.field = 'node_stats.indices.segments.' + opts.field; + } +} + +export class IndicesMemoryMetric extends IndexMemoryMetric { + constructor(opts) { + super({ + ...opts, + type: 'cluster' + }); + + // override the field set by the super constructor + this.field = 'index_stats.total.segments.' + opts.field; + } +} + +export class SingleIndexMemoryMetric extends IndexMemoryMetric { + constructor(opts) { + super({ + ...opts, + type: 'index' + }); + + // override the field set by the super constructor + this.field = 'index_stats.total.segments.' + opts.field; + } +} diff --git a/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/metrics.js b/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/metrics.js new file mode 100644 index 00000000000000..b6fa138b3f52f3 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/metrics.js @@ -0,0 +1,980 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { QuotaMetric } from '../classes'; +import { + RequestRateMetric, + LatencyMetric, + ElasticsearchMetric, + SingleIndexMemoryMetric, + IndexMemoryMetric, + NodeIndexMemoryMetric, + ThreadPoolQueueMetric, + ThreadPoolRejectedMetric +} from './classes'; +import { + LARGE_FLOAT, + SMALL_FLOAT, + SMALL_BYTES, + LARGE_BYTES, + LARGE_ABBREVIATED +} from '../../../../common/formatting'; + +export const metrics = { + cluster_index_request_rate_primary: new RequestRateMetric({ + title: 'Indexing Rate', // title to use for the chart + label: 'Primary Shards', // label to use for this line in the chart + field: 'indices_stats._all.primaries.indexing.index_total', + description: 'Number of documents being indexed for primary shards.', + type: 'index' + }), + cluster_index_request_rate_total: new RequestRateMetric({ + field: 'indices_stats._all.total.indexing.index_total', + title: 'Indexing Rate', + label: 'Total Shards', + description: + 'Number of documents being indexed for primary and replica shards.', + type: 'index' + }), + cluster_search_request_rate: new RequestRateMetric({ + field: 'indices_stats._all.total.search.query_total', + title: 'Search Rate', + label: 'Total Shards', + description: + 'Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!', // eslint-disable-line max-len + type: 'cluster' + }), + cluster_index_latency: new LatencyMetric({ + metric: 'index', + fieldSource: 'indices_stats._all.primaries', + field: 'indices_stats._all.primaries.indexing.index_total', + label: 'Indexing Latency', + description: + 'Average latency for indexing documents, which is time it takes to index documents divided by number that were indexed. This only considers primary shards.', // eslint-disable-line max-len + type: 'cluster' + }), + node_index_latency: new LatencyMetric({ + metric: 'index', + fieldSource: 'node_stats.indices', + field: 'node_stats.indices.indexing.index_total', + title: 'Latency', + label: 'Indexing', + description: + 'Average latency for indexing documents, which is time it takes to index documents divided by number that were indexed. This considers any shard located on this node, including replicas.', // eslint-disable-line max-len + type: 'node' + }), + index_latency: new LatencyMetric({ + metric: 'index', + fieldSource: 'index_stats.primaries', + field: 'index_stats.primaries.indexing.index_total', + label: 'Indexing Latency', + description: + 'Average latency for indexing documents, which is time it takes to index documents divided by number that were indexed. This only considers primary shards.', // eslint-disable-line max-len + type: 'cluster' + }), + cluster_query_latency: new LatencyMetric({ + metric: 'query', + fieldSource: 'indices_stats._all.total', + field: 'indices_stats._all.total.search.query_total', + label: 'Search Latency', + description: + 'Average latency for searching, which is time it takes to execute searches divided by number of searches submitted. This considers primary and replica shards.', // eslint-disable-line max-len + type: 'cluster' + }), + node_query_latency: new LatencyMetric({ + metric: 'query', + fieldSource: 'node_stats.indices', + field: 'node_stats.indices.search.query_total', + title: 'Latency', + label: 'Search', + description: + 'Average latency for searching, which is time it takes to execute searches divided by number of searches submitted. This considers primary and replica shards.', // eslint-disable-line max-len + type: 'node' + }), + query_latency: new LatencyMetric({ + metric: 'query', + fieldSource: 'index_stats.total', + field: 'index_stats.total.search.query_total', + label: 'Search Latency', + description: + 'Average latency for searching, which is time it takes to execute searches divided by number of searches submitted. This considers primary and replica shards.', // eslint-disable-line max-len + type: 'cluster' + }), + index_indexing_primaries_time: new ElasticsearchMetric({ + field: 'index_stats.primaries.indexing.index_time_in_millis', + title: 'Request Time', + label: 'Indexing (Primaries)', + description: + 'Amount of time spent performing index operations on primary shards only.', + type: 'index', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + index_indexing_total_time: new ElasticsearchMetric({ + field: 'index_stats.total.indexing.index_time_in_millis', + title: 'Request Time', + label: 'Indexing', + description: + 'Amount of time spent performing index operations on primary and replica shards.', + type: 'index', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + index_indexing_total: new ElasticsearchMetric({ + field: 'index_stats.primaries.indexing.index_total', + title: 'Request Rate', + label: 'Index Total', + description: 'Amount of indexing operations.', + type: 'index', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + index_mem_overall: new SingleIndexMemoryMetric({ + field: 'memory_in_bytes', + label: 'Lucene Total', + description: + 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.' + }), + index_mem_overall_1: new SingleIndexMemoryMetric({ + field: 'memory_in_bytes', + title: 'Index Memory - Lucene 1', + label: 'Lucene Total', + description: + 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.' + }), + index_mem_overall_2: new SingleIndexMemoryMetric({ + field: 'memory_in_bytes', + title: 'Index Memory - Lucene 2', + label: 'Lucene Total', + description: + 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.' + }), + index_mem_overall_3: new SingleIndexMemoryMetric({ + field: 'memory_in_bytes', + title: 'Index Memory - Lucene 3', + label: 'Lucene Total', + description: + 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.' + }), + index_mem_doc_values: new SingleIndexMemoryMetric({ + field: 'doc_values_memory_in_bytes', + label: 'Doc Values', + description: + 'Heap memory used by Doc Values. This is a part of Lucene Total.' + }), + // Note: This is not segment memory, unlike SingleIndexMemoryMetrics + index_mem_fielddata: new IndexMemoryMetric({ + field: 'index_stats.total.fielddata.memory_size_in_bytes', + label: 'Fielddata', + description: + 'Heap memory used by Fielddata (e.g., global ordinals or explicitly enabled fielddata on text fields). This is for the same shards, but not a part of Lucene Total.', // eslint-disable-line max-len + type: 'index' + }), + index_mem_fixed_bit_set: new SingleIndexMemoryMetric({ + field: 'fixed_bit_set_memory_in_bytes', + label: 'Fixed Bitsets', + description: + 'Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.' + }), + index_mem_norms: new SingleIndexMemoryMetric({ + field: 'norms_memory_in_bytes', + label: 'Norms', + description: + 'Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.' + }), + index_mem_points: new SingleIndexMemoryMetric({ + field: 'points_memory_in_bytes', + label: 'Points', + description: + 'Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.' + }), + // Note: This is not segment memory, unlike SingleIndexMemoryMetrics + index_mem_query_cache: new IndexMemoryMetric({ + field: 'index_stats.total.query_cache.memory_size_in_bytes', + title: 'Index Memory - Elasticsearch', + label: 'Query Cache', + description: + 'Heap memory used by Query Cache (e.g., cached filters). This is for the same shards, but not a part of Lucene Total.', + type: 'index' + }), + // Note: This is not segment memory, unlike SingleIndexMemoryMetrics + index_mem_request_cache: new IndexMemoryMetric({ + field: 'index_stats.total.request_cache.memory_size_in_bytes', + label: 'Request Cache', + description: + 'Heap memory used by Request Cache (e.g., instant aggregations). This is for the same shards, but not a part of Lucene Total.', // eslint-disable-line max-len + type: 'index' + }), + index_mem_stored_fields: new SingleIndexMemoryMetric({ + field: 'stored_fields_memory_in_bytes', + label: 'Stored Fields', + description: + 'Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.' + }), + index_mem_term_vectors: new SingleIndexMemoryMetric({ + field: 'term_vectors_memory_in_bytes', + label: 'Term Vectors', + description: + 'Heap memory used by Term Vectors. This is a part of Lucene Total.' + }), + index_mem_terms: new SingleIndexMemoryMetric({ + field: 'terms_memory_in_bytes', + label: 'Terms', + description: + 'Heap memory used by Terms (e.g., text). This is a part of Lucene Total.' + }), + index_mem_versions: new SingleIndexMemoryMetric({ + field: 'version_map_memory_in_bytes', + label: 'Version Map', + description: + 'Heap memory used by Versioning (e.g., updates and deletes). This is NOT a part of Lucene Total.' + }), + index_mem_writer: new SingleIndexMemoryMetric({ + field: 'index_writer_memory_in_bytes', + label: 'Index Writer', + description: + 'Heap memory used by the Index Writer. This is NOT a part of Lucene Total.' + }), + index_request_rate_primary: new ElasticsearchMetric({ + field: 'index_stats.primaries.indexing.index_total', + title: 'Indexing Rate', + label: 'Primary Shards', + description: 'Number of documents being indexed for primary shards.', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '/s', + type: 'index', + derivative: true + }), + index_request_rate_total: new RequestRateMetric({ + field: 'index_stats.total.indexing.index_total', + title: 'Indexing Rate', + label: 'Total Shards', + description: + 'Number of documents being indexed for primary and replica shards.', + type: 'index' + }), + index_searching_time: new ElasticsearchMetric({ + field: 'index_stats.total.search.query_time_in_millis', + title: 'Request Time', + label: 'Search', + description: + 'Amount of time spent performing search operations (per shard).', + type: 'index', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + index_searching_total: new ElasticsearchMetric({ + field: 'index_stats.total.search.query_total', + title: 'Request Rate', + label: 'Search Total', + description: 'Amount of search operations (per shard).', + type: 'index', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + index_segment_count_primaries: new ElasticsearchMetric({ + field: 'index_stats.primaries.segments.count', + title: 'Segment Count', + label: 'Primaries', + description: 'Number of segments for primary shards.', + type: 'index', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + index_segment_count_total: new ElasticsearchMetric({ + field: 'index_stats.total.segments.count', + title: 'Segment Count', + label: 'Total', + description: 'Number of segments for primary and replica shards.', + type: 'index', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + index_segment_merge_primaries_size: new ElasticsearchMetric({ + field: 'index_stats.primaries.merges.total_size_in_bytes', + title: 'Disk', + label: 'Merges (Primaries)', + description: 'Size of merges on primary shards.', + type: 'index', + derivative: true, + format: LARGE_BYTES, + metricAgg: 'max', + units: 'B' + }), + index_segment_merge_total_size: new ElasticsearchMetric({ + field: 'index_stats.total.merges.total_size_in_bytes', + title: 'Disk', + label: 'Merges', + description: 'Size of merges on primary and replica shards.', + type: 'index', + derivative: true, + format: LARGE_BYTES, + metricAgg: 'max', + units: 'B' + }), + index_segment_refresh_primaries_time: new ElasticsearchMetric({ + field: 'index_stats.primaries.refresh.total_time_in_millis', + title: 'Refresh Time', + label: 'Primaries', + description: + 'Amount of time spent to perform refresh operations on primary shards.', + type: 'index', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + index_segment_refresh_total_time: new ElasticsearchMetric({ + field: 'index_stats.total.refresh.total_time_in_millis', + title: 'Refresh Time', + label: 'Total', + description: + 'Amount of time spent to perform refresh operations on primary and replica shards.', + type: 'index', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + index_throttling_indexing_primaries_time: new ElasticsearchMetric({ + field: 'index_stats.primaries.indexing.throttle_time_in_millis', + title: 'Throttle Time', + label: 'Indexing (Primaries)', + description: + 'Amount of time spent throttling index operations on primary shards.', + type: 'index', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + index_throttling_indexing_total_time: new ElasticsearchMetric({ + field: 'index_stats.total.indexing.throttle_time_in_millis', + title: 'Throttle Time', + label: 'Indexing', + description: + 'Amount of time spent throttling index operations on primary and replica shards.', + type: 'index', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + index_store_primaries_size: new ElasticsearchMetric({ + field: 'index_stats.primaries.store.size_in_bytes', + title: 'Disk', + label: 'Store (Primaries)', + description: 'Size of primary shards on disk.', + type: 'index', + derivative: false, + format: LARGE_BYTES, + metricAgg: 'max', + units: 'B' + }), + index_store_total_size: new ElasticsearchMetric({ + field: 'index_stats.total.store.size_in_bytes', + title: 'Disk', + label: 'Store', + description: 'Size of primary and replica shards on disk.', + type: 'index', + derivative: false, + format: LARGE_BYTES, + metricAgg: 'max', + units: 'B' + }), + search_request_rate: new RequestRateMetric({ + field: 'index_stats.total.search.query_total', + title: 'Search Rate', + label: 'Total Shards', + description: + 'Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!', // eslint-disable-line max-len + type: 'cluster' + }), + node_cgroup_periods: new ElasticsearchMetric({ + field: 'node_stats.os.cgroup.cpu.stat.number_of_elapsed_periods', + title: 'Cgroup CFS Stats', + label: 'Cgroup Elapsed Periods', + description: + 'The number of sampling periods from the Completely Fair Scheduler (CFS). Compare against the number of times throttled.', + type: 'node', + format: LARGE_FLOAT, + metricAgg: 'max', + derivative: true, + units: '' + }), + node_cgroup_throttled: new ElasticsearchMetric({ + field: 'node_stats.os.cgroup.cpu.stat.time_throttled_nanos', + title: 'Cgroup CPU Performance', + label: 'Cgroup Throttling', + description: + 'The amount of throttled time, reported in nanoseconds, of the Cgroup.', + type: 'node', + format: LARGE_ABBREVIATED, + metricAgg: 'max', + derivative: true, + units: 'ns' + }), + node_cgroup_throttled_count: new ElasticsearchMetric({ + field: 'node_stats.os.cgroup.cpu.stat.number_of_times_throttled', + title: 'Cgroup CFS Stats', + label: 'Cgroup Throttled Count', + description: + 'The number of times that the CPU was throttled by the Cgroup.', + type: 'node', + format: LARGE_FLOAT, + metricAgg: 'max', + derivative: true, + units: '' + }), + node_cgroup_usage: new ElasticsearchMetric({ + field: 'node_stats.os.cgroup.cpuacct.usage_nanos', + title: 'Cgroup CPU Performance', + label: 'Cgroup Usage', + description: + 'The usage, reported in nanoseconds, of the Cgroup. Compare this with the throttling to discover issues.', + type: 'node', + format: LARGE_ABBREVIATED, + metricAgg: 'max', + derivative: true, + units: 'ns' + }), + ...(() => { + // CGroup CPU Utilization Fields + const quotaMetricConfig = { + app: 'elasticsearch', + uuidField: 'source_node.uuid', + timestampField: 'timestamp', + fieldSource: 'node_stats.os.cgroup', + usageField: 'cpuacct.usage_nanos', + periodsField: 'cpu.stat.number_of_elapsed_periods', + quotaField: 'cpu.cfs_quota_micros', + field: 'node_stats.process.cpu.percent', // backup field if quota is not configured + label: 'Cgroup CPU Utilization', + description: + 'CPU Usage time compared to the CPU quota shown in percentage. If CPU ' + + 'quotas are not set, then no data will be shown.', + type: 'node' + }; + return { + node_cgroup_quota: new QuotaMetric({ + ...quotaMetricConfig, + title: 'CPU Utilization' + }), + node_cgroup_quota_as_cpu_utilization: new QuotaMetric({ + ...quotaMetricConfig, + label: 'CPU Utilization' // override the "Cgroup CPU..." label + }) + }; + })(), + node_cpu_utilization: new ElasticsearchMetric({ + field: 'node_stats.process.cpu.percent', + label: 'CPU Utilization', + description: 'Percentage of CPU usage for the Elasticsearch process.', + type: 'node', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '%' + }), + node_segment_count: new ElasticsearchMetric({ + field: 'node_stats.indices.segments.count', + label: 'Segment Count', + description: + 'Maximum segment count for primary and replica shards on this node.', + type: 'node', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + node_jvm_gc_old_count: new ElasticsearchMetric({ + field: 'node_stats.jvm.gc.collectors.old.collection_count', + title: 'GC Count', + label: 'Old', + description: 'Number of old Garbage Collections.', + derivative: true, + format: SMALL_FLOAT, + metricAgg: 'max', + units: '', + type: 'node' + }), + node_jvm_gc_old_time: new ElasticsearchMetric({ + field: 'node_stats.jvm.gc.collectors.old.collection_time_in_millis', + title: 'GC Duration', + label: 'Old', + derivative: true, + description: 'Time spent performing old Garbage Collections.', + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms', + type: 'node' + }), + node_jvm_gc_young_count: new ElasticsearchMetric({ + field: 'node_stats.jvm.gc.collectors.young.collection_count', + title: 'GC Count', + label: 'Young', + description: 'Number of young Garbage Collections.', + derivative: true, + format: SMALL_FLOAT, + metricAgg: 'max', + units: '', + type: 'node' + }), + node_jvm_gc_young_time: new ElasticsearchMetric({ + field: 'node_stats.jvm.gc.collectors.young.collection_time_in_millis', + title: 'GC Duration', + label: 'Young', + description: 'Time spent performing young Garbage Collections.', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms', + type: 'node' + }), + node_jvm_mem_max_in_bytes: new ElasticsearchMetric({ + field: 'node_stats.jvm.mem.heap_max_in_bytes', + title: 'JVM Heap', + label: 'Max Heap', + description: 'Total heap available to Elasticsearch running in the JVM.', + type: 'node', + format: SMALL_BYTES, + metricAgg: 'max', + units: 'B' + }), + node_jvm_mem_used_in_bytes: new ElasticsearchMetric({ + field: 'node_stats.jvm.mem.heap_used_in_bytes', + title: 'JVM Heap', + label: 'Used Heap', + description: 'Total heap used by Elasticsearch running in the JVM.', + type: 'node', + format: SMALL_BYTES, + metricAgg: 'max', + units: 'B' + }), + node_jvm_mem_percent: new ElasticsearchMetric({ + field: 'node_stats.jvm.mem.heap_used_percent', + title: 'JVM Heap', + label: 'Used Heap', + description: 'Total heap used by Elasticsearch running in the JVM.', + type: 'node', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '%' + }), + node_load_average: new ElasticsearchMetric({ + field: 'node_stats.os.cpu.load_average.1m', + title: 'System Load', + label: '1m', + description: 'Load average over the last minute.', + type: 'node', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + node_index_mem_overall: new NodeIndexMemoryMetric({ + field: 'memory_in_bytes', + label: 'Lucene Total', + description: + 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.' // eslint-disable-line max-len + }), + node_index_mem_overall_1: new NodeIndexMemoryMetric({ + field: 'memory_in_bytes', + label: 'Lucene Total', + title: 'Index Memory - Lucene 1', + description: + 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.' // eslint-disable-line max-len + }), + node_index_mem_overall_2: new NodeIndexMemoryMetric({ + field: 'memory_in_bytes', + label: 'Lucene Total', + title: 'Index Memory - Lucene 2', + description: + 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.' // eslint-disable-line max-len + }), + node_index_mem_overall_3: new NodeIndexMemoryMetric({ + field: 'memory_in_bytes', + label: 'Lucene Total', + title: 'Index Memory - Lucene 3', + description: + 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.' // eslint-disable-line max-len + }), + node_index_mem_doc_values: new NodeIndexMemoryMetric({ + field: 'doc_values_memory_in_bytes', + label: 'Doc Values', + description: + 'Heap memory used by Doc Values. This is a part of Lucene Total.' + }), + // Note: This is not segment memory, unlike the rest of the SingleIndexMemoryMetrics + node_index_mem_fielddata: new IndexMemoryMetric({ + field: 'node_stats.indices.fielddata.memory_size_in_bytes', + label: 'Fielddata', + description: + 'Heap memory used by Fielddata (e.g., global ordinals or explicitly enabled fielddata on text fields). This is for the same shards, but not a part of Lucene Total.', // eslint-disable-line max-len + type: 'node' + }), + node_index_mem_fixed_bit_set: new NodeIndexMemoryMetric({ + field: 'fixed_bit_set_memory_in_bytes', + label: 'Fixed Bitsets', + description: + 'Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.' + }), + node_index_mem_norms: new NodeIndexMemoryMetric({ + field: 'norms_memory_in_bytes', + label: 'Norms', + description: + 'Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.' + }), + node_index_mem_points: new NodeIndexMemoryMetric({ + field: 'points_memory_in_bytes', + label: 'Points', + description: + 'Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.' + }), + // Note: This is not segment memory, unlike SingleIndexMemoryMetrics + node_index_mem_query_cache: new IndexMemoryMetric({ + field: 'node_stats.indices.query_cache.memory_size_in_bytes', + label: 'Query Cache', + title: 'Index Memory - Elasticsearch', + description: + 'Heap memory used by Query Cache (e.g., cached filters). This is for the same shards, but not a part of Lucene Total.', + type: 'node' + }), + // Note: This is not segment memory, unlike SingleIndexMemoryMetrics + node_index_mem_request_cache: new IndexMemoryMetric({ + field: 'node_stats.indices.request_cache.memory_size_in_bytes', + label: 'Request Cache', + description: + 'Heap memory used by Request Cache (e.g., instant aggregations). This is for the same shards, but not a part of Lucene Total.', // eslint-disable-line max-len + type: 'node' + }), + node_index_mem_stored_fields: new NodeIndexMemoryMetric({ + field: 'stored_fields_memory_in_bytes', + label: 'Stored Fields', + description: + 'Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.' + }), + node_index_mem_term_vectors: new NodeIndexMemoryMetric({ + field: 'term_vectors_memory_in_bytes', + label: 'Term Vectors', + description: + 'Heap memory used by Term Vectors. This is a part of Lucene Total.' + }), + node_index_mem_terms: new NodeIndexMemoryMetric({ + field: 'terms_memory_in_bytes', + label: 'Terms', + description: + 'Heap memory used by Terms (e.g., text). This is a part of Lucene Total.' + }), + node_index_mem_versions: new NodeIndexMemoryMetric({ + field: 'version_map_memory_in_bytes', + label: 'Version Map', + description: + 'Heap memory used by Versioning (e.g., updates and deletes). This is NOT a part of Lucene Total.' + }), + node_index_mem_writer: new NodeIndexMemoryMetric({ + field: 'index_writer_memory_in_bytes', + label: 'Index Writer', + description: + 'Heap memory used by the Index Writer. This is NOT a part of Lucene Total.' + }), + node_index_threads_bulk_queue: new ElasticsearchMetric({ + field: 'node_stats.thread_pool.bulk.queue', + title: 'Indexing Threads', + label: 'Bulk Queue', + description: 'Number of bulk operations in the queue.', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '', + min: 0 + }), + node_index_threads_bulk_rejected: new ElasticsearchMetric({ + field: 'node_stats.thread_pool.bulk.rejected', + title: 'Indexing Threads', + label: 'Bulk Rejections', + description: + 'Number of bulk operations that have been rejected, which occurs when the queue is full.', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '', + min: 0 + }), + node_index_threads_get_queue: new ElasticsearchMetric({ + field: 'node_stats.thread_pool.get.queue', + title: 'Read Threads', + label: 'GET Queue', + description: 'Number of GET operations in the queue.', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '', + min: 0 + }), + node_index_threads_get_rejected: new ElasticsearchMetric({ + field: 'node_stats.thread_pool.get.rejected', + title: 'Read Threads', + label: 'GET Rejections', + description: + 'Number of GET operations that have been rejected, which occurs when the queue is full.', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '', + min: 0 + }), + node_index_threads_index_queue: new ElasticsearchMetric({ + field: 'node_stats.thread_pool.index.queue', + title: 'Indexing Threads', + label: 'Index Queue', + description: 'Number of non-bulk, index operations in the queue.', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '', + min: 0 + }), + node_index_threads_index_rejected: new ElasticsearchMetric({ + field: 'node_stats.thread_pool.index.rejected', + title: 'Indexing Threads', + label: 'Index Rejections', + description: + 'Number of non-bulk, index operations that have been rejected, which occurs when the queue is full. ' + + 'Generally indicates that bulk should be used.', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '', + min: 0 + }), + node_index_threads_search_queue: new ElasticsearchMetric({ + field: 'node_stats.thread_pool.search.queue', + title: 'Read Threads', + label: 'Search Queue', + description: + 'Number of search operations in the queue (e.g., shard level searches).', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '', + min: 0 + }), + node_index_threads_search_rejected: new ElasticsearchMetric({ + field: 'node_stats.thread_pool.search.rejected', + title: 'Read Threads', + label: 'Search Rejections', + description: + 'Number of search operations that have been rejected, which occurs when the queue is full.', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '', + min: 0 + }), + node_index_total: new ElasticsearchMetric({ + field: 'node_stats.indices.indexing.index_total', + title: 'Request Rate', + label: 'Indexing Total', + description: 'Amount of indexing operations.', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + node_index_time: new ElasticsearchMetric({ + field: 'node_stats.indices.indexing.index_time_in_millis', + title: 'Indexing Time', + label: 'Index Time', + description: 'Amount of time spent on indexing operations.', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + node_free_space: new ElasticsearchMetric({ + field: 'node_stats.fs.total.available_in_bytes', + label: 'Disk Free Space', + description: 'Free disk space available on the node.', + type: 'node', + format: SMALL_BYTES, + metricAgg: 'max', + units: '' + }), + node_search_total: new ElasticsearchMetric({ + field: 'node_stats.indices.search.query_total', + title: 'Request Rate', + label: 'Search Total', + description: 'Amount of search operations (per shard).', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + node_threads_queued_bulk: new ThreadPoolQueueMetric({ + field: 'node_stats.thread_pool.bulk.queue', + label: 'Bulk', + description: + 'Number of bulk indexing operations waiting to be processed on this node. A single bulk request can create multiple bulk operations.' // eslint-disable-line max-len + }), + node_threads_queued_generic: new ThreadPoolQueueMetric({ + field: 'node_stats.thread_pool.generic.queue', + label: 'Generic', + description: + 'Number of generic (internal) operations waiting to be processed on this node.' + }), + node_threads_queued_get: new ThreadPoolQueueMetric({ + field: 'node_stats.thread_pool.get.queue', + title: 'Thread Queue', + label: 'Get', + description: + 'Number of get operations waiting to be processed on this node.' + }), + node_threads_queued_index: new ThreadPoolQueueMetric({ + field: 'node_stats.thread_pool.index.queue', + label: 'Index', + description: + 'Number of non-bulk, index operations waiting to be processed on this node.' + }), + node_threads_queued_management: new ThreadPoolQueueMetric({ + field: 'node_stats.thread_pool.management.queue', + label: 'Management', + description: + 'Number of management (internal) operations waiting to be processed on this node.' + }), + node_threads_queued_search: new ThreadPoolQueueMetric({ + field: 'node_stats.thread_pool.search.queue', + label: 'Search', + description: + 'Number of search operations waiting to be processed on this node. A single search request can create multiple search operations.' // eslint-disable-line max-len + }), + node_threads_queued_watcher: new ThreadPoolQueueMetric({ + field: 'node_stats.thread_pool.watcher.queue', + label: 'Watcher', + description: + 'Number of Watcher operations waiting to be processed on this node.' + }), + node_threads_rejected_bulk: new ThreadPoolRejectedMetric({ + field: 'node_stats.thread_pool.bulk.rejected', + label: 'Bulk', + description: 'Bulk rejections. These occur when the queue is full.' + }), + node_threads_rejected_generic: new ThreadPoolRejectedMetric({ + field: 'node_stats.thread_pool.generic.rejected', + label: 'Generic', + description: + 'Generic (internal) rejections. These occur when the queue is full.' + }), + node_threads_rejected_get: new ThreadPoolRejectedMetric({ + field: 'node_stats.thread_pool.get.rejected', + label: 'Get', + description: 'Get rejections. These occur when the queue is full.' + }), + node_threads_rejected_index: new ThreadPoolRejectedMetric({ + field: 'node_stats.thread_pool.index.rejected', + label: 'Index', + description: + 'Index rejections. These occur when the queue is full. You should look at bulk indexing.' + }), + node_threads_rejected_management: new ThreadPoolRejectedMetric({ + field: 'node_stats.thread_pool.management.rejected', + label: 'Management', + description: + 'Get (internal) rejections. These occur when the queue is full.' + }), + node_threads_rejected_search: new ThreadPoolRejectedMetric({ + field: 'node_stats.thread_pool.search.rejected', + label: 'Search', + description: + 'Search rejections. These occur when the queue is full. This can indicate over-sharding.' + }), + node_threads_rejected_watcher: new ThreadPoolRejectedMetric({ + field: 'node_stats.thread_pool.watcher.rejected', + label: 'Watcher', + description: + 'Watch rejections. These occur when the queue is full. This can indicate stuck-Watches.' + }), + node_throttle_index_time: new ElasticsearchMetric({ + field: 'node_stats.indices.indexing.throttle_time_in_millis', + title: 'Indexing Time', + label: 'Index Throttling Time', + description: + 'Amount of time spent with index throttling, which indicates slow disks on a node.', + type: 'node', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms', + min: 0 + }), + index_throttle_time: new ElasticsearchMetric({ + field: 'index_stats.primaries.indexing.throttle_time_in_millis', + label: 'Index Throttling Time', + description: + 'Amount of time spent with index throttling, which indicates slow merging.', + type: 'index', + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + index_document_count: new ElasticsearchMetric({ + field: 'index_stats.primaries.docs.count', + label: 'Document Count', + description: 'Total number of documents, only including primary shards.', + type: 'index', + format: LARGE_ABBREVIATED, + metricAgg: 'max', + units: '' + }), + index_search_request_rate: new RequestRateMetric({ + field: 'index_stats.total.search.query_total', + title: 'Search Rate', + label: 'Total Shards', + description: + 'Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!', // eslint-disable-line max-len + type: 'index' + }), + index_merge_rate: new RequestRateMetric({ + field: 'index_stats.total.merges.total_size_in_bytes', + label: 'Merge Rate', + description: + 'Amount in bytes of merged segments. Larger numbers indicate heavier disk activity.', + type: 'index' + }), + index_refresh_time: new ElasticsearchMetric({ + field: 'total.refresh.total_time_in_millis', + label: 'Total Refresh Time', + description: + 'Time spent on Elasticsearch refresh for primary and replica shards.', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '', + type: 'index', + derivative: true + }) +}; diff --git a/x-pack/plugins/monitoring/server/lib/metrics/index.js b/x-pack/plugins/monitoring/server/lib/metrics/index.js index 08660f8e5ef367..460dbb51a3edc5 100644 --- a/x-pack/plugins/monitoring/server/lib/metrics/index.js +++ b/x-pack/plugins/monitoring/server/lib/metrics/index.js @@ -4,12 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -export { - LatencyMetric, - QuotaMetric, - ElasticsearchMetric, - LogstashClusterMetric, - BeatsMetric, -} from './classes'; +export { ElasticsearchMetric } from './elasticsearch/classes'; +export { KibanaClusterMetric, KibanaMetric } from './kibana/classes'; +export { LogstashClusterMetric, LogstashMetric } from './logstash/classes'; +export { BeatsClusterMetric, BeatsMetric } from './beats/classes'; export { metrics } from './metrics'; -export { serializeMetric } from './serialize_metric'; diff --git a/x-pack/plugins/monitoring/server/lib/metrics/kibana/classes.js b/x-pack/plugins/monitoring/server/lib/metrics/kibana/classes.js new file mode 100644 index 00000000000000..370c87ab15f6d4 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/kibana/classes.js @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ClusterMetric, Metric } from '../classes'; +import { NORMALIZED_DERIVATIVE_UNIT } from '../../../../common/constants'; + +export class KibanaClusterMetric extends ClusterMetric { + constructor(opts) { + super({ + ...opts, + app: 'kibana', + ...KibanaClusterMetric.getMetricFields() + }); + } + + static getMetricFields() { + return { + uuidField: 'cluster_uuid', + timestampField: 'kibana_stats.timestamp' + }; + } +} + +export class KibanaEventsRateClusterMetric extends KibanaClusterMetric { + constructor(opts) { + super({ + ...opts, + metricAgg: 'max' + }); + + this.aggs = { + kibana_uuids: { + terms: { + field: 'kibana_stats.kibana.uuid', + size: 1000 + }, + aggs: { + event_rate_per_instance: { + max: { + field: this.field + } + } + } + }, + event_rate: { + sum_bucket: { + buckets_path: 'kibana_uuids>event_rate_per_instance', + gap_policy: 'skip' + } + }, + metric_deriv: { + derivative: { + buckets_path: 'event_rate', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + } + }; + } +} + +export class KibanaMetric extends Metric { + constructor(opts) { + super({ + ...opts, + app: 'kibana', + ...KibanaMetric.getMetricFields() + }); + } + + static getMetricFields() { + return { + uuidField: 'kibana_stats.kibana.uuid', + timestampField: 'kibana_stats.timestamp' + }; + } +} + diff --git a/x-pack/plugins/monitoring/server/lib/metrics/kibana/metrics.js b/x-pack/plugins/monitoring/server/lib/metrics/kibana/metrics.js new file mode 100644 index 00000000000000..944ccb07ece0b0 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/kibana/metrics.js @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { KibanaEventsRateClusterMetric, KibanaMetric } from './classes'; +import { + LARGE_FLOAT, + SMALL_FLOAT, + LARGE_BYTES +} from '../../../../common/formatting'; + +export const metrics = { + kibana_cluster_requests: new KibanaEventsRateClusterMetric({ + field: 'kibana_stats.requests.total', + label: 'Client Requests', + description: + 'Total number of client requests received by the Kibana instance.', + format: SMALL_FLOAT, + units: '' + }), + kibana_cluster_max_response_times: new KibanaEventsRateClusterMetric({ + title: 'Client Response Time', + field: 'kibana_stats.response_times.max', + label: 'Max', + description: + 'Maximum response time for client requests to the Kibana instance.', + format: SMALL_FLOAT, + units: 'ms' + }), + kibana_cluster_average_response_times: new KibanaEventsRateClusterMetric({ + title: 'Client Response Time', + field: 'kibana_stats.response_times.average', + label: 'Average', + description: + 'Average response time for client requests to the Kibana instance.', + format: SMALL_FLOAT, + units: 'ms' + }), + kibana_os_load_1m: new KibanaMetric({ + title: 'System Load', + field: 'kibana_stats.os.load.1m', + label: '1m', + description: 'Load average over the last minute.', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + kibana_os_load_5m: new KibanaMetric({ + title: 'System Load', + field: 'kibana_stats.os.load.5m', + label: '5m', + description: 'Load average over the last 5 minutes.', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + kibana_os_load_15m: new KibanaMetric({ + title: 'System Load', + field: 'kibana_stats.os.load.15m', + label: '15m', + description: 'Load average over the last 15 minutes.', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + kibana_memory_heap_size_limit: new KibanaMetric({ + title: 'Memory Size', + field: 'kibana_stats.process.memory.heap.size_limit', + label: 'Heap Size Limit', + description: 'Limit of memory usage before garbage collection.', + format: LARGE_BYTES, + metricAgg: 'max', + units: 'B' + }), + kibana_memory_size: new KibanaMetric({ + title: 'Memory Size', + field: 'kibana_stats.process.memory.resident_set_size_in_bytes', + label: 'Memory Size', + description: 'Total heap used by Kibana running in Node.js.', + format: LARGE_BYTES, + metricAgg: 'max', + units: 'B' + }), + kibana_process_delay: new KibanaMetric({ + field: 'kibana_stats.process.event_loop_delay', + label: 'Event Loop Delay', + description: + 'Delay in Kibana server event loops. Longer delays may indicate blocking events in server thread, such as synchronous functions taking large amount of CPU time.', // eslint-disable-line max-len + format: SMALL_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + kibana_average_response_times: new KibanaMetric({ + title: 'Client Response Time', + field: 'kibana_stats.response_times.average', + label: 'Average', + description: + 'Average response time for client requests to the Kibana instance.', + format: SMALL_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + kibana_max_response_times: new KibanaMetric({ + title: 'Client Response Time', + field: 'kibana_stats.response_times.max', + label: 'Max', + description: + 'Maximum response time for client requests to the Kibana instance.', + format: SMALL_FLOAT, + metricAgg: 'max', + units: 'ms' + }), + kibana_average_concurrent_connections: new KibanaMetric({ + field: 'kibana_stats.concurrent_connections', + label: 'HTTP Connections', + description: + 'Total number of open socket connections to the Kibana instance.', + format: SMALL_FLOAT, + metricAgg: 'max', + units: '' + }), + kibana_requests: new KibanaMetric({ + field: 'kibana_stats.requests.total', + label: 'Client Requests', + description: + 'Total number of client requests received by the Kibana instance.', + format: SMALL_FLOAT, + metricAgg: 'max', + units: '' + }) +}; diff --git a/x-pack/plugins/monitoring/server/lib/metrics/logstash/classes.js b/x-pack/plugins/monitoring/server/lib/metrics/logstash/classes.js new file mode 100644 index 00000000000000..f2729f597ed8e9 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/logstash/classes.js @@ -0,0 +1,393 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import { ClusterMetric, Metric } from '../classes'; +import { LARGE_FLOAT } from '../../../../common/formatting'; +import { NORMALIZED_DERIVATIVE_UNIT } from '../../../../common/constants'; + +export class LogstashClusterMetric extends ClusterMetric { + constructor(opts) { + super({ + ...opts, + app: 'logstash', + ...LogstashClusterMetric.getMetricFields() + }); + } + + static getMetricFields() { + return { + uuidField: 'cluster_uuid', + timestampField: 'logstash_stats.timestamp' + }; + } +} + +export class LogstashEventsLatencyClusterMetric extends LogstashClusterMetric { + constructor(opts) { + super({ + ...opts, + format: LARGE_FLOAT, + metricAgg: 'max', + units: 'ms' + }); + + this.aggs = { + logstash_uuids: { + terms: { + field: 'logstash_stats.logstash.uuid', + size: 1000 + }, + aggs: { + events_time_in_millis_per_node: { + max: { + field: 'logstash_stats.events.duration_in_millis' + } + }, + events_total_per_node: { + max: { + field: 'logstash_stats.events.out' + } + } + } + }, + events_time_in_millis: { + sum_bucket: { + buckets_path: 'logstash_uuids>events_time_in_millis_per_node', + gap_policy: 'skip' + } + }, + events_total: { + sum_bucket: { + buckets_path: 'logstash_uuids>events_total_per_node', + gap_policy: 'skip' + } + }, + events_time_in_millis_deriv: { + derivative: { + buckets_path: 'events_time_in_millis', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + }, + events_total_deriv: { + derivative: { + buckets_path: 'events_total', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + } + }; + + this.calculation = (bucket, _key, _metric, _bucketSizeInSeconds) => { + const timeInMillisDeriv = _.get( + bucket, + 'events_time_in_millis_deriv.normalized_value', + null + ); + const totalEventsDeriv = _.get( + bucket, + 'events_total_deriv.normalized_value', + null + ); + + return Metric.calculateLatency(timeInMillisDeriv, totalEventsDeriv); + }; + } +} + +export class LogstashEventsRateClusterMetric extends LogstashClusterMetric { + constructor(opts) { + super({ + ...opts, + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '/s' + }); + + this.aggs = { + logstash_uuids: { + terms: { + field: 'logstash_stats.logstash.uuid', + size: 1000 + }, + aggs: { + event_rate_per_node: { + max: { + field: this.field + } + } + } + }, + event_rate: { + sum_bucket: { + buckets_path: 'logstash_uuids>event_rate_per_node', + gap_policy: 'skip' + } + }, + metric_deriv: { + derivative: { + buckets_path: 'event_rate', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + } + }; + } +} + +export class LogstashMetric extends Metric { + constructor(opts) { + super({ + ...opts, + app: 'logstash', + ...LogstashMetric.getMetricFields() + }); + } + + static getMetricFields() { + return { + uuidField: 'logstash_stats.logstash.uuid', + timestampField: 'logstash_stats.timestamp' + }; + } +} + +export class LogstashEventsLatencyMetric extends LogstashMetric { + constructor(opts) { + super({ + ...opts, + format: LARGE_FLOAT, + metricAgg: 'sum', + units: 'ms' + }); + + this.aggs = { + events_time_in_millis: { + max: { field: 'logstash_stats.events.duration_in_millis' } + }, + events_total: { + max: { field: 'logstash_stats.events.out' } + }, + events_time_in_millis_deriv: { + derivative: { + buckets_path: 'events_time_in_millis', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + }, + events_total_deriv: { + derivative: { + buckets_path: 'events_total', + gap_policy: 'skip', + unit: NORMALIZED_DERIVATIVE_UNIT + } + } + }; + + this.calculation = (bucket, _key, _metric, _bucketSizeInSeconds) => { + const timeInMillisDeriv = _.get( + bucket, + 'events_time_in_millis_deriv.normalized_value', + null + ); + const totalEventsDeriv = _.get( + bucket, + 'events_total_deriv.normalized_value', + null + ); + + return Metric.calculateLatency(timeInMillisDeriv, totalEventsDeriv); + }; + } +} + +export class LogstashEventsRateMetric extends LogstashMetric { + constructor(opts) { + super({ + ...opts, + derivative: true, + format: LARGE_FLOAT, + metricAgg: 'max', + units: '/s' + }); + } +} + +export class LogstashPipelineQueueSizeMetric extends LogstashMetric { + constructor(opts) { + super({ ...opts }); + + this.dateHistogramSubAggs = { + pipelines: { + nested: { + path: 'logstash_stats.pipelines' + }, + aggs: { + pipeline_by_id: { + terms: { + field: 'logstash_stats.pipelines.id', + size: 1000 + }, + aggs: { + queue_size_field: { + max: { + field: this.field + } + } + } + }, + total_queue_size_for_node: { + sum_bucket: { + buckets_path: 'pipeline_by_id>queue_size_field' + } + } + } + } + }; + + this.calculation = bucket => + _.get(bucket, 'pipelines.total_queue_size_for_node.value'); + } +} + +export class LogstashPipelineThroughputMetric extends LogstashMetric { + constructor(opts) { + super({ + ...opts, + derivative: false + }); + + this.dateHistogramSubAggs = { + pipelines_nested: { + nested: { + path: 'logstash_stats.pipelines' + }, + aggs: { + by_pipeline_id: { + terms: { + field: 'logstash_stats.pipelines.id', + size: 1000 + }, + aggs: { + throughput: { + sum_bucket: { + buckets_path: 'by_pipeline_hash>throughput' + } + }, + by_pipeline_hash: { + terms: { + field: 'logstash_stats.pipelines.hash', + size: 1000 + }, + aggs: { + throughput: { + sum_bucket: { + buckets_path: 'by_ephemeral_id>throughput' + } + }, + by_ephemeral_id: { + terms: { + field: 'logstash_stats.pipelines.ephemeral_id', + size: 1000 + }, + aggs: { + events_stats: { + stats: { + field: this.field + } + }, + throughput: { + bucket_script: { + script: 'params.max - params.min', + buckets_path: { + min: 'events_stats.min', + max: 'events_stats.max' + } + } + } + } + } + } + } + } + } + } + } + }; + + this.calculation = (bucket, _key, _metric, bucketSizeInSeconds) => { + const pipelineThroughputs = {}; + const pipelineBuckets = _.get( + bucket, + 'pipelines_nested.by_pipeline_id.buckets', + [] + ); + pipelineBuckets.forEach(pipelineBucket => { + pipelineThroughputs[pipelineBucket.key] = bucketSizeInSeconds + ? _.get(pipelineBucket, 'throughput.value') / bucketSizeInSeconds + : undefined; + }); + + return pipelineThroughputs; + }; + } +} + +export class LogstashPipelineNodeCountMetric extends LogstashMetric { + constructor(opts) { + super({ + ...opts, + derivative: false + }); + + this.dateHistogramSubAggs = { + pipelines_nested: { + nested: { + path: 'logstash_stats.pipelines' + }, + aggs: { + by_pipeline_id: { + terms: { + field: 'logstash_stats.pipelines.id', + size: 1000 + }, + aggs: { + to_root: { + reverse_nested: {}, + aggs: { + node_count: { + cardinality: { + field: this.field + } + } + } + } + } + } + } + } + }; + + this.calculation = bucket => { + const pipelineNodesCounts = {}; + const pipelineBuckets = _.get( + bucket, + 'pipelines_nested.by_pipeline_id.buckets', + [] + ); + pipelineBuckets.forEach(pipelineBucket => { + pipelineNodesCounts[pipelineBucket.key] = _.get( + pipelineBucket, + 'to_root.node_count.value' + ); + }); + + return pipelineNodesCounts; + }; + } +} diff --git a/x-pack/plugins/monitoring/server/lib/metrics/logstash/metrics.js b/x-pack/plugins/monitoring/server/lib/metrics/logstash/metrics.js new file mode 100644 index 00000000000000..63ba1c5be0e38d --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/metrics/logstash/metrics.js @@ -0,0 +1,247 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { QuotaMetric } from '../classes'; +import { + LogstashEventsRateClusterMetric, + LogstashEventsLatencyClusterMetric, + LogstashEventsRateMetric, + LogstashEventsLatencyMetric, + LogstashMetric, + LogstashPipelineQueueSizeMetric, + LogstashPipelineThroughputMetric, + LogstashPipelineNodeCountMetric +} from './classes'; +import { + LARGE_FLOAT, + LARGE_BYTES, + SMALL_BYTES, + LARGE_ABBREVIATED +} from '../../../../common/formatting'; + +export const metrics = { + logstash_cluster_events_input_rate: new LogstashEventsRateClusterMetric({ + field: 'logstash_stats.events.in', + label: 'Events Received Rate', + description: + 'Number of events received per second by all Logstash nodes at the inputs stage.' + }), + logstash_cluster_events_output_rate: new LogstashEventsRateClusterMetric({ + field: 'logstash_stats.events.out', + label: 'Events Emitted Rate', + description: + 'Number of events emitted per second by all Logstash nodes at the outputs stage.' + }), + logstash_cluster_events_latency: new LogstashEventsLatencyClusterMetric({ + field: 'logstash_stats.events.out', + label: 'Event Latency', + description: + 'Average time spent by events in the filter and output stages, which is the total ' + + 'time it takes to process events divided by number of events emitted.' + }), + logstash_events_input_rate: new LogstashEventsRateMetric({ + field: 'logstash_stats.events.in', + label: 'Events Received Rate', + description: + 'Number of events received per second by the Logstash node at the inputs stage.' + }), + logstash_events_output_rate: new LogstashEventsRateMetric({ + field: 'logstash_stats.events.out', + label: 'Events Emitted Rate', + description: + 'Number of events emitted per second by the Logstash node at the outputs stage.' + }), + logstash_events_latency: new LogstashEventsLatencyMetric({ + field: 'logstash_stats.events.out', + label: 'Event Latency', + description: + 'Average time spent by events in the filter and output stages, which is the total ' + + 'time it takes to process events divided by number of events emitted.' + }), + logstash_os_load_1m: new LogstashMetric({ + title: 'System Load', + field: 'logstash_stats.os.cpu.load_average.1m', + label: '1m', + description: 'Load average over the last minute.', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + logstash_os_load_5m: new LogstashMetric({ + title: 'System Load', + field: 'logstash_stats.os.cpu.load_average.5m', + label: '5m', + description: 'Load average over the last 5 minutes.', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + logstash_os_load_15m: new LogstashMetric({ + title: 'System Load', + field: 'logstash_stats.os.cpu.load_average.15m', + label: '15m', + description: 'Load average over the last 15 minutes.', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + logstash_node_jvm_mem_max_in_bytes: new LogstashMetric({ + field: 'logstash_stats.jvm.mem.heap_max_in_bytes', + title: 'JVM Heap', + label: 'Max Heap', + description: 'Total heap available to Logstash running in the JVM.', + format: SMALL_BYTES, + metricAgg: 'max', + units: 'B' + }), + logstash_node_jvm_mem_used_in_bytes: new LogstashMetric({ + field: 'logstash_stats.jvm.mem.heap_used_in_bytes', + title: 'JVM Heap', + label: 'Used Heap', + description: 'Total heap used by Logstash running in the JVM.', + format: SMALL_BYTES, + metricAgg: 'max', + units: 'B' + }), + logstash_node_cpu_utilization: new LogstashMetric({ + field: 'logstash_stats.process.cpu.percent', + label: 'CPU Utilization', + description: + 'Percentage of CPU usage reported by the OS (100% is the max).', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '%' + }), + logstash_node_cgroup_periods: new LogstashMetric({ + field: 'logstash_stats.os.cgroup.cpu.stat.number_of_elapsed_periods', + title: 'Cgroup CFS Stats', + label: 'Cgroup Elapsed Periods', + description: + 'The number of sampling periods from the Completely Fair Scheduler (CFS). Compare against the number of times throttled.', + format: LARGE_FLOAT, + metricAgg: 'max', + derivative: true, + units: '' + }), + logstash_node_cgroup_throttled: new LogstashMetric({ + field: 'logstash_stats.os.cgroup.cpu.stat.time_throttled_nanos', + title: 'Cgroup CPU Performance', + label: 'Cgroup Throttling', + description: + 'The amount of throttled time, reported in nanoseconds, of the Cgroup.', + format: LARGE_ABBREVIATED, + metricAgg: 'max', + derivative: true, + units: 'ns' + }), + logstash_node_cgroup_throttled_count: new LogstashMetric({ + field: 'logstash_stats.os.cgroup.cpu.stat.number_of_times_throttled', + title: 'Cgroup CFS Stats', + label: 'Cgroup Throttled Count', + description: + 'The number of times that the CPU was throttled by the Cgroup.', + format: LARGE_FLOAT, + metricAgg: 'max', + derivative: true, + units: '' + }), + logstash_node_cgroup_usage: new LogstashMetric({ + field: 'logstash_stats.os.cgroup.cpuacct.usage_nanos', + title: 'Cgroup CPU Performance', + label: 'Cgroup Usage', + description: + 'The usage, reported in nanoseconds, of the Cgroup. Compare this with the throttling to discover issues.', + format: LARGE_ABBREVIATED, + metricAgg: 'max', + derivative: true, + units: 'ns' + }), + ...(() => { + // CGroup CPU Utilization Fields + const quotaMetricConfig = { + app: 'logstash', + uuidField: 'logstash_stats.logstash.uuid', + timestampField: 'logstash_stats.timestamp', + fieldSource: 'logstash_stats.os.cgroup', + usageField: 'cpuacct.usage_nanos', + periodsField: 'cpu.stat.number_of_elapsed_periods', + quotaField: 'cpu.cfs_quota_micros', + field: 'logstash_stats.process.cpu.percent', // backup field if quota is not configured + label: 'Cgroup CPU Utilization', + description: + 'CPU Usage time compared to the CPU quota shown in percentage. If CPU ' + + 'quotas are not set, then no data will be shown.' + }; + return { + logstash_node_cgroup_quota: new QuotaMetric({ + ...quotaMetricConfig, + title: 'CPU Utilization' + }), + logstash_node_cgroup_quota_as_cpu_utilization: new QuotaMetric({ + ...quotaMetricConfig, + label: 'CPU Utilization' // override the "Cgroup CPU..." label + }) + }; + })(), + logstash_queue_events_count: new LogstashMetric({ + field: 'logstash_stats.queue.events_count', + label: 'Events Queued', + title: 'Persistent Queue Events', + description: + 'Average number of events in the persistent queue waiting to be processed by the filter and output stages.', + format: LARGE_FLOAT, + metricAgg: 'max', + units: '' + }), + logstash_pipeline_queue_size: new LogstashPipelineQueueSizeMetric({ + field: 'logstash_stats.pipelines.queue.queue_size_in_bytes', + label: 'Queue Size', + description: + 'Current size of all persistent queues in the Logstash pipelines on this node.', + title: 'Persistent Queue Size', + format: LARGE_BYTES, + units: 'B' + }), + logstash_pipeline_max_queue_size: new LogstashPipelineQueueSizeMetric({ + field: 'logstash_stats.pipelines.queue.max_queue_size_in_bytes', + label: 'Max Queue Size', + description: 'Maximum size set for the persistent queues on this node.', + format: LARGE_BYTES, + units: 'B' + }), + logstash_cluster_pipeline_throughput: new LogstashPipelineThroughputMetric({ + field: 'logstash_stats.pipelines.events.out', + label: 'Pipeline Throughput', + description: + 'Number of events emitted per second by the Logstash pipeline at the outputs stage.', + format: LARGE_FLOAT, + units: 'e/s' + }), + logstash_node_pipeline_throughput: new LogstashPipelineThroughputMetric({ + uuidField: 'logstash_stats.logstash.uuid', // TODO: add comment explaining why + field: 'logstash_stats.pipelines.events.out', + label: 'Pipeline Throughput', + description: + 'Number of events emitted per second by the Logstash pipeline at the outputs stage.', + format: LARGE_FLOAT, + units: 'e/s' + }), + logstash_cluster_pipeline_nodes_count: new LogstashPipelineNodeCountMetric({ + field: 'logstash_stats.logstash.uuid', + label: 'Pipeline Node Count', + description: 'Number of nodes on which the Logstash pipeline is running.', + format: LARGE_FLOAT, + units: '' + }), + logstash_node_pipeline_nodes_count: new LogstashPipelineNodeCountMetric({ + uuidField: 'logstash_stats.logstash.uuid', // TODO: add comment explaining why + field: 'logstash_stats.logstash.uuid', + label: 'Pipeline Node Count', + description: 'Number of nodes on which the Logstash pipeline is running.', + format: LARGE_FLOAT, + units: '' + }) +}; diff --git a/x-pack/plugins/monitoring/server/lib/metrics/metrics.js b/x-pack/plugins/monitoring/server/lib/metrics/metrics.js index 2fbc6a5474982a..89c84d7784e270 100644 --- a/x-pack/plugins/monitoring/server/lib/metrics/metrics.js +++ b/x-pack/plugins/monitoring/server/lib/metrics/metrics.js @@ -4,1446 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - BeatsEventsRateClusterMetric, - BeatsByteRateClusterMetric, - BeatsEventsRateMetric, - BeatsMetric, - BeatsByteRateMetric, - BeatsCpuUtilizationMetric, - ElasticsearchMetric, - IndexMemoryMetric, - KibanaEventsRateClusterMetric, - KibanaMetric, - LatencyMetric, - LogstashEventsLatencyClusterMetric, - LogstashEventsLatencyMetric, - LogstashEventsRateClusterMetric, - LogstashEventsRateMetric, - LogstashMetric, - LogstashPipelineQueueSizeMetric, - LogstashPipelineThroughputMetric, - LogstashPipelineNodeCountMetric, - NodeIndexMemoryMetric, - QuotaMetric, - RequestRateMetric, - SingleIndexMemoryMetric, - ThreadPoolQueueMetric, - ThreadPoolRejectedMetric, - WriteThreadPoolQueueMetric, - WriteThreadPoolRejectedMetric, -} from './classes'; - -import { - LARGE_FLOAT, SMALL_FLOAT, LARGE_BYTES, SMALL_BYTES, LARGE_ABBREVIATED -} from '../../../common/formatting'; - -const metricInstances = { - 'cluster_index_request_rate_primary': new RequestRateMetric({ - title: 'Indexing Rate', // title to use for the chart - label: 'Primary Shards', // label to use for this line in the chart - field: 'indices_stats._all.primaries.indexing.index_total', - description: 'Number of documents being indexed for primary shards.', - type: 'index' - }), - 'cluster_index_request_rate_total': new RequestRateMetric({ - field: 'indices_stats._all.total.indexing.index_total', - title: 'Indexing Rate', - label: 'Total Shards', - description: 'Number of documents being indexed for primary and replica shards.', - type: 'index' - }), - 'cluster_search_request_rate': new RequestRateMetric({ - field: 'indices_stats._all.total.search.query_total', - title: 'Search Rate', - label: 'Total Shards', - description: 'Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!', // eslint-disable-line max-len - type: 'cluster' - }), - 'cluster_index_latency': new LatencyMetric({ - metric: 'index', - fieldSource: 'indices_stats._all.primaries', - field: 'indices_stats._all.primaries.indexing.index_total', - label: 'Indexing Latency', - description: 'Average latency for indexing documents, which is time it takes to index documents divided by number that were indexed. This only considers primary shards.', // eslint-disable-line max-len - type: 'cluster' - }), - 'node_index_latency': new LatencyMetric({ - metric: 'index', - fieldSource: 'node_stats.indices', - field: 'node_stats.indices.indexing.index_total', - title: 'Latency', - label: 'Indexing', - description: 'Average latency for indexing documents, which is time it takes to index documents divided by number that were indexed. This considers any shard located on this node, including replicas.', // eslint-disable-line max-len - type: 'node' - }), - 'index_latency': new LatencyMetric({ - metric: 'index', - fieldSource: 'index_stats.primaries', - field: 'index_stats.primaries.indexing.index_total', - label: 'Indexing Latency', - description: 'Average latency for indexing documents, which is time it takes to index documents divided by number that were indexed. This only considers primary shards.', // eslint-disable-line max-len - type: 'cluster' - }), - 'cluster_query_latency': new LatencyMetric({ - metric: 'query', - fieldSource: 'indices_stats._all.total', - field: 'indices_stats._all.total.search.query_total', - label: 'Search Latency', - description: 'Average latency for searching, which is time it takes to execute searches divided by number of searches submitted. This considers primary and replica shards.', // eslint-disable-line max-len - type: 'cluster' - }), - 'node_query_latency': new LatencyMetric({ - metric: 'query', - fieldSource: 'node_stats.indices', - field: 'node_stats.indices.search.query_total', - title: 'Latency', - label: 'Search', - description: 'Average latency for searching, which is time it takes to execute searches divided by number of searches submitted. This considers primary and replica shards.', // eslint-disable-line max-len - type: 'node' - }), - 'query_latency': new LatencyMetric({ - metric: 'query', - fieldSource: 'index_stats.total', - field: 'index_stats.total.search.query_total', - label: 'Search Latency', - description: 'Average latency for searching, which is time it takes to execute searches divided by number of searches submitted. This considers primary and replica shards.', // eslint-disable-line max-len - type: 'cluster' - }), - 'index_indexing_primaries_time': new ElasticsearchMetric({ - field: 'index_stats.primaries.indexing.index_time_in_millis', - title: 'Request Time', - label: 'Indexing (Primaries)', - description: 'Amount of time spent performing index operations on primary shards only.', - type: 'index', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'index_indexing_total_time': new ElasticsearchMetric({ - field: 'index_stats.total.indexing.index_time_in_millis', - title: 'Request Time', - label: 'Indexing', - description: 'Amount of time spent performing index operations on primary and replica shards.', - type: 'index', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'index_indexing_total': new ElasticsearchMetric({ - field: 'index_stats.primaries.indexing.index_total', - title: 'Request Rate', - label: 'Index Total', - description: 'Amount of indexing operations.', - type: 'index', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'index_mem_overall': new SingleIndexMemoryMetric({ - field: 'memory_in_bytes', - label: 'Lucene Total', - description: 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.' - }), - 'index_mem_overall_1': new SingleIndexMemoryMetric({ - field: 'memory_in_bytes', - title: 'Index Memory - Lucene 1', - label: 'Lucene Total', - description: 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.' - }), - 'index_mem_overall_2': new SingleIndexMemoryMetric({ - field: 'memory_in_bytes', - title: 'Index Memory - Lucene 2', - label: 'Lucene Total', - description: 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.' - }), - 'index_mem_overall_3': new SingleIndexMemoryMetric({ - field: 'memory_in_bytes', - title: 'Index Memory - Lucene 3', - label: 'Lucene Total', - description: 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.' - }), - 'index_mem_doc_values': new SingleIndexMemoryMetric({ - field: 'doc_values_memory_in_bytes', - label: 'Doc Values', - description: 'Heap memory used by Doc Values. This is a part of Lucene Total.' - }), - // Note: This is not segment memory, unlike SingleIndexMemoryMetrics - 'index_mem_fielddata': new IndexMemoryMetric({ - field: 'index_stats.total.fielddata.memory_size_in_bytes', - label: 'Fielddata', - description: 'Heap memory used by Fielddata (e.g., global ordinals or explicitly enabled fielddata on text fields). This is for the same shards, but not a part of Lucene Total.', // eslint-disable-line max-len - type: 'index' - }), - 'index_mem_fixed_bit_set': new SingleIndexMemoryMetric({ - field: 'fixed_bit_set_memory_in_bytes', - label: 'Fixed Bitsets', - description: 'Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.' - }), - 'index_mem_norms': new SingleIndexMemoryMetric({ - field: 'norms_memory_in_bytes', - label: 'Norms', - description: 'Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.' - }), - 'index_mem_points': new SingleIndexMemoryMetric({ - field: 'points_memory_in_bytes', - label: 'Points', - description: 'Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.' - }), - // Note: This is not segment memory, unlike SingleIndexMemoryMetrics - 'index_mem_query_cache': new IndexMemoryMetric({ - field: 'index_stats.total.query_cache.memory_size_in_bytes', - title: 'Index Memory - Elasticsearch', - label: 'Query Cache', - description: 'Heap memory used by Query Cache (e.g., cached filters). This is for the same shards, but not a part of Lucene Total.', - type: 'index' - }), - // Note: This is not segment memory, unlike SingleIndexMemoryMetrics - 'index_mem_request_cache': new IndexMemoryMetric({ - field: 'index_stats.total.request_cache.memory_size_in_bytes', - label: 'Request Cache', - description: 'Heap memory used by Request Cache (e.g., instant aggregations). This is for the same shards, but not a part of Lucene Total.', // eslint-disable-line max-len - type: 'index' - }), - 'index_mem_stored_fields': new SingleIndexMemoryMetric({ - field: 'stored_fields_memory_in_bytes', - label: 'Stored Fields', - description: 'Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.' - }), - 'index_mem_term_vectors': new SingleIndexMemoryMetric({ - field: 'term_vectors_memory_in_bytes', - label: 'Term Vectors', - description: 'Heap memory used by Term Vectors. This is a part of Lucene Total.' - }), - 'index_mem_terms': new SingleIndexMemoryMetric({ - field: 'terms_memory_in_bytes', - label: 'Terms', - description: 'Heap memory used by Terms (e.g., text). This is a part of Lucene Total.' - }), - 'index_mem_versions': new SingleIndexMemoryMetric({ - field: 'version_map_memory_in_bytes', - label: 'Version Map', - description: 'Heap memory used by Versioning (e.g., updates and deletes). This is NOT a part of Lucene Total.', - }), - 'index_mem_writer': new SingleIndexMemoryMetric({ - field: 'index_writer_memory_in_bytes', - label: 'Index Writer', - description: 'Heap memory used by the Index Writer. This is NOT a part of Lucene Total.' - }), - 'index_request_rate_primary': new ElasticsearchMetric({ - field: 'index_stats.primaries.indexing.index_total', - title: 'Indexing Rate', - label: 'Primary Shards', - description: 'Number of documents being indexed for primary shards.', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '/s', - type: 'index', - derivative: true - }), - 'index_request_rate_total': new RequestRateMetric({ - field: 'index_stats.total.indexing.index_total', - title: 'Indexing Rate', - label: 'Total Shards', - description: 'Number of documents being indexed for primary and replica shards.', - type: 'index' - }), - 'index_searching_time': new ElasticsearchMetric({ - field: 'index_stats.total.search.query_time_in_millis', - title: 'Request Time', - label: 'Search', - description: 'Amount of time spent performing search operations (per shard).', - type: 'index', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'index_searching_total': new ElasticsearchMetric({ - field: 'index_stats.total.search.query_total', - title: 'Request Rate', - label: 'Search Total', - description: 'Amount of search operations (per shard).', - type: 'index', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'index_segment_count_primaries': new ElasticsearchMetric({ - field: 'index_stats.primaries.segments.count', - title: 'Segment Count', - label: 'Primaries', - description: 'Number of segments for primary shards.', - type: 'index', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'index_segment_count_total': new ElasticsearchMetric({ - field: 'index_stats.total.segments.count', - title: 'Segment Count', - label: 'Total', - description: 'Number of segments for primary and replica shards.', - type: 'index', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'index_segment_merge_primaries_size': new ElasticsearchMetric({ - field: 'index_stats.primaries.merges.total_size_in_bytes', - title: 'Disk', - label: 'Merges (Primaries)', - description: 'Size of merges on primary shards.', - type: 'index', - derivative: true, - format: LARGE_BYTES, - metricAgg: 'max', - units: 'B' - }), - 'index_segment_merge_total_size': new ElasticsearchMetric({ - field: 'index_stats.total.merges.total_size_in_bytes', - title: 'Disk', - label: 'Merges', - description: 'Size of merges on primary and replica shards.', - type: 'index', - derivative: true, - format: LARGE_BYTES, - metricAgg: 'max', - units: 'B' - }), - 'index_segment_refresh_primaries_time': new ElasticsearchMetric({ - field: 'index_stats.primaries.refresh.total_time_in_millis', - title: 'Refresh Time', - label: 'Primaries', - description: 'Amount of time spent to perform refresh operations on primary shards.', - type: 'index', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'index_segment_refresh_total_time': new ElasticsearchMetric({ - field: 'index_stats.total.refresh.total_time_in_millis', - title: 'Refresh Time', - label: 'Total', - description: 'Amount of time spent to perform refresh operations on primary and replica shards.', - type: 'index', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'index_throttling_indexing_primaries_time': new ElasticsearchMetric({ - field: 'index_stats.primaries.indexing.throttle_time_in_millis', - title: 'Throttle Time', - label: 'Indexing (Primaries)', - description: 'Amount of time spent throttling index operations on primary shards.', - type: 'index', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'index_throttling_indexing_total_time': new ElasticsearchMetric({ - field: 'index_stats.total.indexing.throttle_time_in_millis', - title: 'Throttle Time', - label: 'Indexing', - description: 'Amount of time spent throttling index operations on primary and replica shards.', - type: 'index', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'index_store_primaries_size': new ElasticsearchMetric({ - field: 'index_stats.primaries.store.size_in_bytes', - title: 'Disk', - label: 'Store (Primaries)', - description: 'Size of primary shards on disk.', - type: 'index', - derivative: false, - format: LARGE_BYTES, - metricAgg: 'max', - units: 'B' - }), - 'index_store_total_size': new ElasticsearchMetric({ - field: 'index_stats.total.store.size_in_bytes', - title: 'Disk', - label: 'Store', - description: 'Size of primary and replica shards on disk.', - type: 'index', - derivative: false, - format: LARGE_BYTES, - metricAgg: 'max', - units: 'B' - }), - 'search_request_rate': new RequestRateMetric({ - field: 'index_stats.total.search.query_total', - title: 'Search Rate', - label: 'Total Shards', - description: 'Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!', // eslint-disable-line max-len - type: 'cluster' - }), - 'node_cgroup_periods': new ElasticsearchMetric({ - field: 'node_stats.os.cgroup.cpu.stat.number_of_elapsed_periods', - title: 'Cgroup CFS Stats', - label: 'Cgroup Elapsed Periods', - description: ( - 'The number of sampling periods from the Completely Fair Scheduler (CFS). Compare against the number of times throttled.' - ), - type: 'node', - format: LARGE_FLOAT, - metricAgg: 'max', - derivative: true, - units: '' - }), - 'node_cgroup_throttled': new ElasticsearchMetric({ - field: 'node_stats.os.cgroup.cpu.stat.time_throttled_nanos', - title: 'Cgroup CPU Performance', - label: 'Cgroup Throttling', - description: 'The amount of throttled time, reported in nanoseconds, of the Cgroup.', - type: 'node', - format: LARGE_ABBREVIATED, - metricAgg: 'max', - derivative: true, - units: 'ns' - }), - 'node_cgroup_throttled_count': new ElasticsearchMetric({ - field: 'node_stats.os.cgroup.cpu.stat.number_of_times_throttled', - title: 'Cgroup CFS Stats', - label: 'Cgroup Throttled Count', - description: 'The number of times that the CPU was throttled by the Cgroup.', - type: 'node', - format: LARGE_FLOAT, - metricAgg: 'max', - derivative: true, - units: '' - }), - 'node_cgroup_usage': new ElasticsearchMetric({ - field: 'node_stats.os.cgroup.cpuacct.usage_nanos', - title: 'Cgroup CPU Performance', - label: 'Cgroup Usage', - description: 'The usage, reported in nanoseconds, of the Cgroup. Compare this with the throttling to discover issues.', - type: 'node', - format: LARGE_ABBREVIATED, - metricAgg: 'max', - derivative: true, - units: 'ns' - }), - ...(() => { - // CGroup CPU Utilization Fields - const quotaMetricConfig = { - app: 'elasticsearch', - uuidField: 'source_node.uuid', - timestampField: 'timestamp', - fieldSource: 'node_stats.os.cgroup', - usageField: 'cpuacct.usage_nanos', - periodsField: 'cpu.stat.number_of_elapsed_periods', - quotaField: 'cpu.cfs_quota_micros', - field: 'node_stats.process.cpu.percent', // backup field if quota is not configured - label: 'Cgroup CPU Utilization', - description: ( - 'CPU Usage time compared to the CPU quota shown in percentage. If CPU ' + - 'quotas are not set, then no data will be shown.' - ), - type: 'node' - }; - return { - 'node_cgroup_quota': new QuotaMetric({ - ...quotaMetricConfig, - title: 'CPU Utilization' - }), - 'node_cgroup_quota_as_cpu_utilization': new QuotaMetric({ - ...quotaMetricConfig, - label: 'CPU Utilization' // override the "Cgroup CPU..." label - }) - }; - })(), - 'node_cpu_utilization': new ElasticsearchMetric({ - field: 'node_stats.process.cpu.percent', - label: 'CPU Utilization', - description: 'Percentage of CPU usage for the Elasticsearch process.', - type: 'node', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '%' - }), - 'node_segment_count': new ElasticsearchMetric({ - field: 'node_stats.indices.segments.count', - label: 'Segment Count', - description: 'Maximum segment count for primary and replica shards on this node.', - type: 'node', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'node_jvm_gc_old_count': new ElasticsearchMetric({ - field: 'node_stats.jvm.gc.collectors.old.collection_count', - title: 'GC Count', - label: 'Old', - description: 'Number of old Garbage Collections.', - derivative: true, - format: SMALL_FLOAT, - metricAgg: 'max', - units: '', - type: 'node' - }), - 'node_jvm_gc_old_time': new ElasticsearchMetric({ - field: 'node_stats.jvm.gc.collectors.old.collection_time_in_millis', - title: 'GC Duration', - label: 'Old', - derivative: true, - description: 'Time spent performing old Garbage Collections.', - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms', - type: 'node' - }), - 'node_jvm_gc_young_count': new ElasticsearchMetric({ - field: 'node_stats.jvm.gc.collectors.young.collection_count', - title: 'GC Count', - label: 'Young', - description: 'Number of young Garbage Collections.', - derivative: true, - format: SMALL_FLOAT, - metricAgg: 'max', - units: '', - type: 'node' - }), - 'node_jvm_gc_young_time': new ElasticsearchMetric({ - field: 'node_stats.jvm.gc.collectors.young.collection_time_in_millis', - title: 'GC Duration', - label: 'Young', - description: 'Time spent performing young Garbage Collections.', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms', - type: 'node' - }), - 'node_jvm_mem_max_in_bytes': new ElasticsearchMetric({ - field: 'node_stats.jvm.mem.heap_max_in_bytes', - title: 'JVM Heap', - label: 'Max Heap', - description: 'Total heap available to Elasticsearch running in the JVM.', - type: 'node', - format: SMALL_BYTES, - metricAgg: 'max', - units: 'B' - }), - 'node_jvm_mem_used_in_bytes': new ElasticsearchMetric({ - field: 'node_stats.jvm.mem.heap_used_in_bytes', - title: 'JVM Heap', - label: 'Used Heap', - description: 'Total heap used by Elasticsearch running in the JVM.', - type: 'node', - format: SMALL_BYTES, - metricAgg: 'max', - units: 'B' - }), - 'node_jvm_mem_percent': new ElasticsearchMetric({ - field: 'node_stats.jvm.mem.heap_used_percent', - title: 'JVM Heap', - label: 'Used Heap', - description: 'Total heap used by Elasticsearch running in the JVM.', - type: 'node', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '%' - }), - 'node_load_average': new ElasticsearchMetric({ - field: 'node_stats.os.cpu.load_average.1m', - title: 'System Load', - label: '1m', - description: 'Load average over the last minute.', - type: 'node', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'node_index_mem_overall': new NodeIndexMemoryMetric({ - field: 'memory_in_bytes', - label: 'Lucene Total', - description: 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.' // eslint-disable-line max-len - }), - 'node_index_mem_overall_1': new NodeIndexMemoryMetric({ - field: 'memory_in_bytes', - label: 'Lucene Total', - title: 'Index Memory - Lucene 1', - description: 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.' // eslint-disable-line max-len - }), - 'node_index_mem_overall_2': new NodeIndexMemoryMetric({ - field: 'memory_in_bytes', - label: 'Lucene Total', - title: 'Index Memory - Lucene 2', - description: 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.' // eslint-disable-line max-len - }), - 'node_index_mem_overall_3': new NodeIndexMemoryMetric({ - field: 'memory_in_bytes', - label: 'Lucene Total', - title: 'Index Memory - Lucene 3', - description: 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.' // eslint-disable-line max-len - }), - 'node_index_mem_doc_values': new NodeIndexMemoryMetric({ - field: 'doc_values_memory_in_bytes', - label: 'Doc Values', - description: 'Heap memory used by Doc Values. This is a part of Lucene Total.' - }), - // Note: This is not segment memory, unlike the rest of the SingleIndexMemoryMetrics - 'node_index_mem_fielddata': new IndexMemoryMetric({ - field: 'node_stats.indices.fielddata.memory_size_in_bytes', - label: 'Fielddata', - description: 'Heap memory used by Fielddata (e.g., global ordinals or explicitly enabled fielddata on text fields). This is for the same shards, but not a part of Lucene Total.', // eslint-disable-line max-len - type: 'node' - }), - 'node_index_mem_fixed_bit_set': new NodeIndexMemoryMetric({ - field: 'fixed_bit_set_memory_in_bytes', - label: 'Fixed Bitsets', - description: 'Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.' - }), - 'node_index_mem_norms': new NodeIndexMemoryMetric({ - field: 'norms_memory_in_bytes', - label: 'Norms', - description: 'Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.' - }), - 'node_index_mem_points': new NodeIndexMemoryMetric({ - field: 'points_memory_in_bytes', - label: 'Points', - description: 'Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.' - }), - // Note: This is not segment memory, unlike SingleIndexMemoryMetrics - 'node_index_mem_query_cache': new IndexMemoryMetric({ - field: 'node_stats.indices.query_cache.memory_size_in_bytes', - label: 'Query Cache', - title: 'Index Memory - Elasticsearch', - description: 'Heap memory used by Query Cache (e.g., cached filters). This is for the same shards, but not a part of Lucene Total.', - type: 'node' - }), - // Note: This is not segment memory, unlike SingleIndexMemoryMetrics - 'node_index_mem_request_cache': new IndexMemoryMetric({ - field: 'node_stats.indices.request_cache.memory_size_in_bytes', - label: 'Request Cache', - description: 'Heap memory used by Request Cache (e.g., instant aggregations). This is for the same shards, but not a part of Lucene Total.', // eslint-disable-line max-len - type: 'node' - }), - 'node_index_mem_stored_fields': new NodeIndexMemoryMetric({ - field: 'stored_fields_memory_in_bytes', - label: 'Stored Fields', - description: 'Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.' - }), - 'node_index_mem_term_vectors': new NodeIndexMemoryMetric({ - field: 'term_vectors_memory_in_bytes', - label: 'Term Vectors', - description: 'Heap memory used by Term Vectors. This is a part of Lucene Total.' - }), - 'node_index_mem_terms': new NodeIndexMemoryMetric({ - field: 'terms_memory_in_bytes', - label: 'Terms', - description: 'Heap memory used by Terms (e.g., text). This is a part of Lucene Total.' - }), - 'node_index_mem_versions': new NodeIndexMemoryMetric({ - field: 'version_map_memory_in_bytes', - label: 'Version Map', - description: 'Heap memory used by Versioning (e.g., updates and deletes). This is NOT a part of Lucene Total.' - }), - 'node_index_mem_writer': new NodeIndexMemoryMetric({ - field: 'index_writer_memory_in_bytes', - label: 'Index Writer', - description: 'Heap memory used by the Index Writer. This is NOT a part of Lucene Total.' - }), - 'node_index_threads_write_queue': new WriteThreadPoolQueueMetric({ - title: 'Indexing Threads', - label: 'Write Queue', - description: ( - 'Number of index, bulk, and write operations in the queue. ' + - 'The bulk threadpool was renamed to write in 6.3, and the index threadpool is deprecated.' - ), - }), - 'node_index_threads_write_rejected': new WriteThreadPoolRejectedMetric({ - field: 'node_stats.thread_pool.bulk.rejected', - title: 'Indexing Threads', - label: 'Write Rejections', - description: ( - 'Number of index, bulk, and write operations that have been rejected, which occurs when the queue is full. ' + - 'The bulk threadpool was renamed to write in 6.3, and the index threadpool is deprecated.' - ), - }), - 'node_index_threads_get_queue': new ElasticsearchMetric({ - field: 'node_stats.thread_pool.get.queue', - title: 'Read Threads', - label: 'GET Queue', - description: 'Number of GET operations in the queue.', - type: 'node', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '', - min: 0 - }), - 'node_index_threads_get_rejected': new ElasticsearchMetric({ - field: 'node_stats.thread_pool.get.rejected', - title: 'Read Threads', - label: 'GET Rejections', - description: 'Number of GET operations that have been rejected, which occurs when the queue is full.', - type: 'node', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '', - min: 0 - }), - 'node_index_threads_search_queue': new ElasticsearchMetric({ - field: 'node_stats.thread_pool.search.queue', - title: 'Read Threads', - label: 'Search Queue', - description: 'Number of search operations in the queue (e.g., shard level searches).', - type: 'node', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '', - min: 0 - }), - 'node_index_threads_search_rejected': new ElasticsearchMetric({ - field: 'node_stats.thread_pool.search.rejected', - title: 'Read Threads', - label: 'Search Rejections', - description: 'Number of search operations that have been rejected, which occurs when the queue is full.', - type: 'node', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '', - min: 0 - }), - 'node_index_total': new ElasticsearchMetric({ - field: 'node_stats.indices.indexing.index_total', - title: 'Request Rate', - label: 'Indexing Total', - description: 'Amount of indexing operations.', - type: 'node', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'node_index_time': new ElasticsearchMetric({ - field: 'node_stats.indices.indexing.index_time_in_millis', - title: 'Indexing Time', - label: 'Index Time', - description: 'Amount of time spent on indexing operations.', - type: 'node', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'node_free_space': new ElasticsearchMetric({ - field: 'node_stats.fs.total.available_in_bytes', - label: 'Disk Free Space', - description: 'Free disk space available on the node.', - type: 'node', - format: SMALL_BYTES, - metricAgg: 'max', - units: '' - }), - 'node_search_total': new ElasticsearchMetric({ - field: 'node_stats.indices.search.query_total', - title: 'Request Rate', - label: 'Search Total', - description: 'Amount of search operations (per shard).', - type: 'node', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'node_threads_queued_bulk': new ThreadPoolQueueMetric({ - field: 'node_stats.thread_pool.bulk.queue', - label: 'Bulk', - description: 'Number of bulk indexing operations waiting to be processed on this node. A single bulk request can create multiple bulk operations.' // eslint-disable-line max-len - }), - 'node_threads_queued_generic': new ThreadPoolQueueMetric({ - field: 'node_stats.thread_pool.generic.queue', - label: 'Generic', - description: 'Number of generic (internal) operations waiting to be processed on this node.' - }), - 'node_threads_queued_get': new ThreadPoolQueueMetric({ - field: 'node_stats.thread_pool.get.queue', - title: 'Thread Queue', - label: 'Get', - description: 'Number of get operations waiting to be processed on this node.' - }), - 'node_threads_queued_index': new ThreadPoolQueueMetric({ - field: 'node_stats.thread_pool.index.queue', - label: 'Index', - description: 'Number of non-bulk, index operations waiting to be processed on this node.' - }), - 'node_threads_queued_management': new ThreadPoolQueueMetric({ - field: 'node_stats.thread_pool.management.queue', - label: 'Management', - description: 'Number of management (internal) operations waiting to be processed on this node.' - }), - 'node_threads_queued_search': new ThreadPoolQueueMetric({ - field: 'node_stats.thread_pool.search.queue', - label: 'Search', - description: 'Number of search operations waiting to be processed on this node. A single search request can create multiple search operations.' // eslint-disable-line max-len - }), - 'node_threads_queued_watcher': new ThreadPoolQueueMetric({ - field: 'node_stats.thread_pool.watcher.queue', - label: 'Watcher', - description: 'Number of Watcher operations waiting to be processed on this node.' - }), - 'node_threads_rejected_bulk': new ThreadPoolRejectedMetric({ - field: 'node_stats.thread_pool.bulk.rejected', - label: 'Bulk', - description: 'Bulk rejections. These occur when the queue is full.' - }), - 'node_threads_rejected_generic': new ThreadPoolRejectedMetric({ - field: 'node_stats.thread_pool.generic.rejected', - label: 'Generic', - description: 'Generic (internal) rejections. These occur when the queue is full.' - }), - 'node_threads_rejected_get': new ThreadPoolRejectedMetric({ - field: 'node_stats.thread_pool.get.rejected', - label: 'Get', - description: 'Get rejections. These occur when the queue is full.' - }), - 'node_threads_rejected_index': new ThreadPoolRejectedMetric({ - field: 'node_stats.thread_pool.index.rejected', - label: 'Index', - description: 'Index rejections. These occur when the queue is full. You should look at bulk indexing.' - }), - 'node_threads_rejected_management': new ThreadPoolRejectedMetric({ - field: 'node_stats.thread_pool.management.rejected', - label: 'Management', - description: 'Get (internal) rejections. These occur when the queue is full.' - }), - 'node_threads_rejected_search': new ThreadPoolRejectedMetric({ - field: 'node_stats.thread_pool.search.rejected', - label: 'Search', - description: 'Search rejections. These occur when the queue is full. This can indicate over-sharding.' - }), - 'node_threads_rejected_watcher': new ThreadPoolRejectedMetric({ - field: 'node_stats.thread_pool.watcher.rejected', - label: 'Watcher', - description: 'Watch rejections. These occur when the queue is full. This can indicate stuck-Watches.' - }), - 'node_throttle_index_time': new ElasticsearchMetric({ - field: 'node_stats.indices.indexing.throttle_time_in_millis', - title: 'Indexing Time', - label: 'Index Throttling Time', - description: 'Amount of time spent with index throttling, which indicates slow disks on a node.', - type: 'node', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms', - min: 0 - }), - 'index_throttle_time': new ElasticsearchMetric({ - field: 'index_stats.primaries.indexing.throttle_time_in_millis', - label: 'Index Throttling Time', - description: 'Amount of time spent with index throttling, which indicates slow merging.', - type: 'index', - derivative: true, - format: LARGE_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'index_document_count': new ElasticsearchMetric({ - field: 'index_stats.primaries.docs.count', - label: 'Document Count', - description: 'Total number of documents, only including primary shards.', - type: 'index', - format: LARGE_ABBREVIATED, - metricAgg: 'max', - units: '' - }), - 'index_search_request_rate': new RequestRateMetric({ - field: 'index_stats.total.search.query_total', - title: 'Search Rate', - label: 'Total Shards', - description: 'Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!', // eslint-disable-line max-len - type: 'index' - }), - 'index_merge_rate': new RequestRateMetric({ - field: 'index_stats.total.merges.total_size_in_bytes', - label: 'Merge Rate', - description: 'Amount in bytes of merged segments. Larger numbers indicate heavier disk activity.', - type: 'index' - }), - 'index_refresh_time': new ElasticsearchMetric({ - field: 'total.refresh.total_time_in_millis', - label: 'Total Refresh Time', - description: 'Time spent on Elasticsearch refresh for primary and replica shards.', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '', - type: 'index', - derivative: true - }), - 'kibana_cluster_requests': new KibanaEventsRateClusterMetric({ - field: 'kibana_stats.requests.total', - label: 'Client Requests', - description: 'Total number of client requests received by the Kibana instance.', - format: SMALL_FLOAT, - units: '' - }), - 'kibana_cluster_max_response_times': new KibanaEventsRateClusterMetric({ - title: 'Client Response Time', - field: 'kibana_stats.response_times.max', - label: 'Max', - description: 'Maximum response time for client requests to the Kibana instance.', - format: SMALL_FLOAT, - units: 'ms' - }), - 'kibana_cluster_average_response_times': new KibanaEventsRateClusterMetric({ - title: 'Client Response Time', - field: 'kibana_stats.response_times.average', - label: 'Average', - description: 'Average response time for client requests to the Kibana instance.', - format: SMALL_FLOAT, - units: 'ms' - }), - 'kibana_os_load_1m': new KibanaMetric({ - title: 'System Load', - field: 'kibana_stats.os.load.1m', - label: '1m', - description: 'Load average over the last minute.', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'kibana_os_load_5m': new KibanaMetric({ - title: 'System Load', - field: 'kibana_stats.os.load.5m', - label: '5m', - description: 'Load average over the last 5 minutes.', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'kibana_os_load_15m': new KibanaMetric({ - title: 'System Load', - field: 'kibana_stats.os.load.15m', - label: '15m', - description: 'Load average over the last 15 minutes.', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'kibana_memory_heap_size_limit': new KibanaMetric({ - title: 'Memory Size', - field: 'kibana_stats.process.memory.heap.size_limit', - label: 'Heap Size Limit', - description: 'Limit of memory usage before garbage collection.', - format: LARGE_BYTES, - metricAgg: 'max', - units: 'B' - }), - 'kibana_memory_size': new KibanaMetric({ - title: 'Memory Size', - field: 'kibana_stats.process.memory.resident_set_size_in_bytes', - label: 'Memory Size', - description: 'Total heap used by Kibana running in Node.js.', - format: LARGE_BYTES, - metricAgg: 'max', - units: 'B' - }), - 'kibana_process_delay': new KibanaMetric({ - field: 'kibana_stats.process.event_loop_delay', - label: 'Event Loop Delay', - description: 'Delay in Kibana server event loops. Longer delays may indicate blocking events in server thread, such as synchronous functions taking large amount of CPU time.', // eslint-disable-line max-len - format: SMALL_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'kibana_average_response_times': new KibanaMetric({ - title: 'Client Response Time', - field: 'kibana_stats.response_times.average', - label: 'Average', - description: 'Average response time for client requests to the Kibana instance.', - format: SMALL_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'kibana_max_response_times': new KibanaMetric({ - title: 'Client Response Time', - field: 'kibana_stats.response_times.max', - label: 'Max', - description: 'Maximum response time for client requests to the Kibana instance.', - format: SMALL_FLOAT, - metricAgg: 'max', - units: 'ms' - }), - 'kibana_average_concurrent_connections': new KibanaMetric({ - field: 'kibana_stats.concurrent_connections', - label: 'HTTP Connections', - description: 'Total number of open socket connections to the Kibana instance.', - format: SMALL_FLOAT, - metricAgg: 'max', - units: '' - }), - 'kibana_requests': new KibanaMetric({ - field: 'kibana_stats.requests.total', - label: 'Client Requests', - description: 'Total number of client requests received by the Kibana instance.', - format: SMALL_FLOAT, - metricAgg: 'max', - units: '' - }), - 'logstash_cluster_events_input_rate': new LogstashEventsRateClusterMetric({ - field: 'logstash_stats.events.in', - label: 'Events Received Rate', - description: 'Number of events received per second by all Logstash nodes at the inputs stage.', - }), - 'logstash_cluster_events_output_rate': new LogstashEventsRateClusterMetric({ - field: 'logstash_stats.events.out', - label: 'Events Emitted Rate', - description: 'Number of events emitted per second by all Logstash nodes at the outputs stage.', - }), - 'logstash_cluster_events_latency': new LogstashEventsLatencyClusterMetric({ - field: 'logstash_stats.events.out', - label: 'Event Latency', - description: ( - 'Average time spent by events in the filter and output stages, which is the total ' + - 'time it takes to process events divided by number of events emitted.' - ), - }), - 'logstash_events_input_rate': new LogstashEventsRateMetric({ - field: 'logstash_stats.events.in', - label: 'Events Received Rate', - description: 'Number of events received per second by the Logstash node at the inputs stage.', - }), - 'logstash_events_output_rate': new LogstashEventsRateMetric({ - field: 'logstash_stats.events.out', - label: 'Events Emitted Rate', - description: 'Number of events emitted per second by the Logstash node at the outputs stage.', - }), - 'logstash_events_latency': new LogstashEventsLatencyMetric({ - field: 'logstash_stats.events.out', - label: 'Event Latency', - description: ( - 'Average time spent by events in the filter and output stages, which is the total ' + - 'time it takes to process events divided by number of events emitted.' - ), - }), - 'logstash_os_load_1m': new LogstashMetric({ - title: 'System Load', - field: 'logstash_stats.os.cpu.load_average.1m', - label: '1m', - description: 'Load average over the last minute.', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'logstash_os_load_5m': new LogstashMetric({ - title: 'System Load', - field: 'logstash_stats.os.cpu.load_average.5m', - label: '5m', - description: 'Load average over the last 5 minutes.', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'logstash_os_load_15m': new LogstashMetric({ - title: 'System Load', - field: 'logstash_stats.os.cpu.load_average.15m', - label: '15m', - description: 'Load average over the last 15 minutes.', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'logstash_node_jvm_mem_max_in_bytes': new LogstashMetric({ - field: 'logstash_stats.jvm.mem.heap_max_in_bytes', - title: 'JVM Heap', - label: 'Max Heap', - description: 'Total heap available to Logstash running in the JVM.', - format: SMALL_BYTES, - metricAgg: 'max', - units: 'B' - }), - 'logstash_node_jvm_mem_used_in_bytes': new LogstashMetric({ - field: 'logstash_stats.jvm.mem.heap_used_in_bytes', - title: 'JVM Heap', - label: 'Used Heap', - description: 'Total heap used by Logstash running in the JVM.', - format: SMALL_BYTES, - metricAgg: 'max', - units: 'B' - }), - 'logstash_node_cpu_utilization': new LogstashMetric({ - field: 'logstash_stats.process.cpu.percent', - label: 'CPU Utilization', - description: 'Percentage of CPU usage reported by the OS (100% is the max).', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '%' - }), - 'logstash_node_cgroup_periods': new LogstashMetric({ - field: 'logstash_stats.os.cgroup.cpu.stat.number_of_elapsed_periods', - title: 'Cgroup CFS Stats', - label: 'Cgroup Elapsed Periods', - description: ( - 'The number of sampling periods from the Completely Fair Scheduler (CFS). Compare against the number of times throttled.' - ), - format: LARGE_FLOAT, - metricAgg: 'max', - derivative: true, - units: '' - }), - 'logstash_node_cgroup_throttled': new LogstashMetric({ - field: 'logstash_stats.os.cgroup.cpu.stat.time_throttled_nanos', - title: 'Cgroup CPU Performance', - label: 'Cgroup Throttling', - description: 'The amount of throttled time, reported in nanoseconds, of the Cgroup.', - format: LARGE_ABBREVIATED, - metricAgg: 'max', - derivative: true, - units: 'ns' - }), - 'logstash_node_cgroup_throttled_count': new LogstashMetric({ - field: 'logstash_stats.os.cgroup.cpu.stat.number_of_times_throttled', - title: 'Cgroup CFS Stats', - label: 'Cgroup Throttled Count', - description: 'The number of times that the CPU was throttled by the Cgroup.', - format: LARGE_FLOAT, - metricAgg: 'max', - derivative: true, - units: '' - }), - 'logstash_node_cgroup_usage': new LogstashMetric({ - field: 'logstash_stats.os.cgroup.cpuacct.usage_nanos', - title: 'Cgroup CPU Performance', - label: 'Cgroup Usage', - description: 'The usage, reported in nanoseconds, of the Cgroup. Compare this with the throttling to discover issues.', - format: LARGE_ABBREVIATED, - metricAgg: 'max', - derivative: true, - units: 'ns' - }), - ...(() => { - // CGroup CPU Utilization Fields - const quotaMetricConfig = { - app: 'logstash', - uuidField: 'logstash_stats.logstash.uuid', - timestampField: 'logstash_stats.timestamp', - fieldSource: 'logstash_stats.os.cgroup', - usageField: 'cpuacct.usage_nanos', - periodsField: 'cpu.stat.number_of_elapsed_periods', - quotaField: 'cpu.cfs_quota_micros', - field: 'logstash_stats.process.cpu.percent', // backup field if quota is not configured - label: 'Cgroup CPU Utilization', - description: ( - 'CPU Usage time compared to the CPU quota shown in percentage. If CPU ' + - 'quotas are not set, then no data will be shown.' - ) - }; - return { - 'logstash_node_cgroup_quota': new QuotaMetric({ - ...quotaMetricConfig, - title: 'CPU Utilization' - }), - 'logstash_node_cgroup_quota_as_cpu_utilization': new QuotaMetric({ - ...quotaMetricConfig, - label: 'CPU Utilization' // override the "Cgroup CPU..." label - }) - }; - })(), - 'logstash_queue_events_count': new LogstashMetric({ - field: 'logstash_stats.queue.events_count', - label: 'Events Queued', - title: 'Persistent Queue Events', - description: 'Average number of events in the persistent queue waiting to be processed by the filter and output stages.', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '' - }), - 'logstash_pipeline_queue_size': new LogstashPipelineQueueSizeMetric({ - field: 'logstash_stats.pipelines.queue.queue_size_in_bytes', - label: 'Queue Size', - description: 'Current size of all persistent queues in the Logstash pipelines on this node.', - title: 'Persistent Queue Size', - format: LARGE_BYTES, - units: 'B' - }), - 'logstash_pipeline_max_queue_size': new LogstashPipelineQueueSizeMetric({ - field: 'logstash_stats.pipelines.queue.max_queue_size_in_bytes', - label: 'Max Queue Size', - description: 'Maximum size set for the persistent queues on this node.', - format: LARGE_BYTES, - units: 'B' - }), - 'logstash_cluster_pipeline_throughput': new LogstashPipelineThroughputMetric({ - field: 'logstash_stats.pipelines.events.out', - label: 'Pipeline Throughput', - description: 'Number of events emitted per second by the Logstash pipeline at the outputs stage.', - format: LARGE_FLOAT, - units: 'e/s' - }), - 'logstash_node_pipeline_throughput': new LogstashPipelineThroughputMetric({ - uuidField: 'logstash_stats.logstash.uuid', // TODO: add comment explaining why - field: 'logstash_stats.pipelines.events.out', - label: 'Pipeline Throughput', - description: 'Number of events emitted per second by the Logstash pipeline at the outputs stage.', - format: LARGE_FLOAT, - units: 'e/s' - }), - 'logstash_cluster_pipeline_nodes_count': new LogstashPipelineNodeCountMetric({ - field: 'logstash_stats.logstash.uuid', - label: 'Pipeline Node Count', - description: 'Number of nodes on which the Logstash pipeline is running.', - format: LARGE_FLOAT, - units: '' - }), - 'logstash_node_pipeline_nodes_count': new LogstashPipelineNodeCountMetric({ - uuidField: 'logstash_stats.logstash.uuid', // TODO: add comment explaining why - field: 'logstash_stats.logstash.uuid', - label: 'Pipeline Node Count', - description: 'Number of nodes on which the Logstash pipeline is running.', - format: LARGE_FLOAT, - units: '' - }), - - /* - * Beat Overview - */ - - 'beat_cluster_pipeline_events_total_rate': new BeatsEventsRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.pipeline.events.total', - title: 'Events Rate', - label: 'Total', - description: 'All events newly created in the publishing pipeline', - }), - 'beat_cluster_output_events_total': new BeatsEventsRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.output.events.total', - title: 'Events Rate', - label: 'Emitted', - description: 'Events processed by the output (including retries)', - }), - 'beat_cluster_output_events_ack_rate': new BeatsEventsRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.output.events.acked', - title: 'Events Rate', - label: 'Acknowledged', - description: 'Events acknowledged by the output (includes events dropped by the output)', - }), - 'beat_cluster_pipeline_events_emitted_rate': new BeatsEventsRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.pipeline.events.published', - title: 'Events Rate', - label: 'Queued', - description: 'Events added to the event pipeline queue', - }), - - 'beat_cluster_output_write_bytes_rate': new BeatsByteRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.output.write.bytes', - title: 'Throughput', - label: 'Bytes Sent', - description: 'Bytes written to the output (consists of size of network headers and compressed payload)', - }), - 'beat_cluster_output_read_bytes_rate': new BeatsByteRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.output.read.bytes', - title: 'Throughput', - label: 'Bytes Received', - description: 'Bytes read in response from the output', - }), - - 'beat_cluster_pipeline_events_failed_rate': new BeatsEventsRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.pipeline.events.failed', - title: 'Fail Rates', - label: 'Failed in Pipeline', - description: 'Failures that happened before event was added to the publishing pipeline (output was disabled or publisher client closed)' - }), - 'beat_cluster_pipeline_events_dropped_rate': new BeatsEventsRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.pipeline.events.dropped', - title: 'Fail Rates', - label: 'Dropped in Pipeline', - description: 'Events that have been dropped after N retries (N = max_retries setting)', - }), - 'beat_cluster_output_events_dropped_rate': new BeatsEventsRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.output.events.dropped', - title: 'Fail Rates', - label: 'Dropped in Output', - description: ( - '(Fatal drop) Events dropped by the output as being "invalid." The output ' + - 'still acknowledges the event for the Beat to remove it from the queue.' - ), - }), - 'beat_cluster_pipeline_events_retry_rate': new BeatsEventsRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.pipeline.events.retry', - title: 'Fail Rates', - label: 'Retry in Pipeline', - description: 'Events in the pipeline that are trying again to be sent to the output', - }), - - 'beat_cluster_output_sending_errors': new BeatsEventsRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.output.write.errors', - title: 'Output Errors', - label: 'Sending', - description: 'Errors in writing the response from the output', - }), - 'beat_cluster_output_receiving_errors': new BeatsEventsRateClusterMetric({ - field: 'beats_stats.metrics.libbeat.output.read.errors', - title: 'Output Errors', - label: 'Receiving', - description: 'Errors in reading the response from the output', - }), - - /* - * Beat Detail - */ - - 'beat_pipeline_events_total_rate': new BeatsEventsRateMetric({ - field: 'beats_stats.metrics.libbeat.pipeline.events.total', - title: 'Events Rate', - label: 'New', - description: 'New events sent to the publishing pipeline', - }), - 'beat_output_events_total': new BeatsEventsRateMetric({ - field: 'beats_stats.metrics.libbeat.output.events.total', - title: 'Events Rate', - label: 'Emitted', - description: 'Events processed by the output (including retries)', - }), - 'beat_output_events_ack_rate': new BeatsEventsRateMetric({ - field: 'beats_stats.metrics.libbeat.output.events.acked', - title: 'Events Rate', - label: 'Acknowledged', - description: 'Events acknowledged by the output (includes events dropped by the output)', - }), - 'beat_pipeline_events_emitted_rate': new BeatsEventsRateMetric({ - field: 'beats_stats.metrics.libbeat.pipeline.events.published', - title: 'Events Rate', - label: 'Queued', - description: 'Events added to the event pipeline queue', - }), - - 'beat_pipeline_events_failed_rate': new BeatsEventsRateMetric({ - field: 'beats_stats.metrics.libbeat.pipeline.events.failed', - title: 'Fail Rates', - label: 'Failed in Pipeline', - description: 'Failures that happened before event was added to the publishing pipeline (output was disabled or publisher client closed)' - }), - 'beat_pipeline_events_dropped_rate': new BeatsEventsRateMetric({ - field: 'beats_stats.metrics.libbeat.pipeline.events.dropped', - title: 'Fail Rates', - label: 'Dropped in Pipeline', - description: 'Events that have been dropped after N retries (N = max_retries setting)', - }), - 'beat_output_events_dropped_rate': new BeatsEventsRateMetric({ - field: 'beats_stats.metrics.libbeat.output.events.dropped', - title: 'Fail Rates', - label: 'Dropped in Output', - description: ( - '(Fatal drop) Events dropped by the output as being "invalid." The output ' + - 'still acknowledges the event for the Beat to remove it from the queue.' - ), - }), - 'beat_pipeline_events_retry_rate': new BeatsEventsRateMetric({ - field: 'beats_stats.metrics.libbeat.pipeline.events.retry', - title: 'Fail Rates', - label: 'Retry in Pipeline', - description: 'Events in the pipeline that are trying again to be sent to the output', - }), - - 'beat_bytes_written': new BeatsByteRateMetric({ - field: 'beats_stats.metrics.libbeat.output.write.bytes', - title: 'Throughput', - label: 'Bytes Sent', - description: 'Bytes written to the output (consists of size of network headers and compressed payload)', - }), - 'beat_output_write_bytes_rate': new BeatsByteRateMetric({ - field: 'beats_stats.metrics.libbeat.output.read.bytes', - title: 'Throughput', - label: 'Bytes Received', - description: 'Bytes read in response from the output', - }), - - 'beat_output_sending_errors': new BeatsEventsRateMetric({ - field: 'beats_stats.metrics.libbeat.output.write.errors', - title: 'Output Errors', - label: 'Sending', - description: 'Errors in writing the response from the output', - }), - 'beat_output_receiving_errors': new BeatsEventsRateMetric({ - field: 'beats_stats.metrics.libbeat.output.read.errors', - title: 'Output Errors', - label: 'Receiving', - description: 'Errors in reading the response from the output', - }), - - 'beat_mem_alloc': new BeatsMetric({ - field: 'beats_stats.metrics.beat.memstats.memory_alloc', - label: 'Active', - title: 'Memory', - description: 'Private memory in active use by the Beat', - format: LARGE_BYTES, - metricAgg: 'max', - units: 'B', - }), - 'beat_mem_rss': new BeatsMetric({ - field: 'beats_stats.metrics.beat.memstats.rss', - label: 'Process Total', - title: 'Memory', - description: 'Resident set size of memory reserved by the Beat from the OS', - format: LARGE_BYTES, - metricAgg: 'max', - units: 'B', - }), - 'beat_mem_gc_next': new BeatsMetric({ - field: 'beats_stats.metrics.beat.memstats.gc_next', - label: 'GC Next', - title: 'Memory', - description: 'Limit of allocated memory at which garbage collection will occur', - format: LARGE_BYTES, - metricAgg: 'max', - units: 'B', - }), - - 'beat_cpu_utilization': new BeatsCpuUtilizationMetric ({ - title: 'CPU Utilization', - label: 'Total', - description: 'Percentage of CPU time spent executing (user+kernel mode) for the Beat process', - field: 'beats_stats.metrics.beat.cpu.total.value' - }), - - 'beat_system_os_load_1': new BeatsMetric({ - field: 'beats_stats.metrics.system.load.1', - label: '1m', - title: 'System Load', - description: 'Load average over the last 1 minute', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '', - }), - 'beat_system_os_load_5': new BeatsMetric({ - field: 'beats_stats.metrics.system.load.5', - label: '5m', - title: 'System Load', - description: 'Load average over the last 5 minutes', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '', - }), - 'beat_system_os_load_15': new BeatsMetric({ - field: 'beats_stats.metrics.system.load.15', - label: '15m', - title: 'System Load', - description: 'Load average over the last 15 minutes', - format: LARGE_FLOAT, - metricAgg: 'max', - units: '', - }), +import { metrics as elasticsearchMetrics } from './elasticsearch/metrics'; +import { metrics as kibanaMetrics } from './kibana/metrics'; +import { metrics as logstashMetrics } from './logstash/metrics'; +import { metrics as beatsMetrics } from './beats/metrics'; + +export const metrics = { + ...elasticsearchMetrics, + ...kibanaMetrics, + ...logstashMetrics, + ...beatsMetrics }; - -export const metrics = Object.keys(metricInstances).reduce((accumulated, key) => { - return { - ...accumulated, - [key]: metricInstances[key].toPlainObject() - }; -}, {}); diff --git a/x-pack/plugins/monitoring/server/lib/metrics/serialize_metric.js b/x-pack/plugins/monitoring/server/lib/metrics/serialize_metric.js deleted file mode 100644 index adff13555c0516..00000000000000 --- a/x-pack/plugins/monitoring/server/lib/metrics/serialize_metric.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { pick } from 'lodash'; - -export function serializeMetric(metric) { - // some fields exposed for debugging through HTML comment text - const pickFields = [ - 'app', - 'field', - 'metricAgg', - 'label', - 'title', - 'description', - 'units', - 'format' - ]; - - return { - ...pick(metric, pickFields), - hasCalculation: Boolean(metric.calculation), - isDerivative: metric.derivative, - }; -} diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/indices.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/indices.js index a7ff81e06e5046..caaacc0470dd82 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/indices.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/indices.js @@ -4,12 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { get } from 'lodash'; import Joi from 'joi'; import { getClusterStats } from '../../../../lib/cluster/get_cluster_stats'; import { getClusterStatus } from '../../../../lib/cluster/get_cluster_status'; import { getIndices } from '../../../../lib/elasticsearch/indices'; -import { getShardStats, getUnassignedShards } from '../../../../lib/elasticsearch/shards'; +import { getShardStats } from '../../../../lib/elasticsearch/shards'; import { handleError } from '../../../../lib/errors/handle_error'; import { prefixIndexPattern } from '../../../../lib/ccs_utils'; @@ -22,9 +21,11 @@ export function esIndicesRoute(server) { params: Joi.object({ clusterUuid: Joi.string().required() }), + query: Joi.object({ + show_system_indices: Joi.boolean() + }), payload: Joi.object({ ccs: Joi.string().optional(), - showSystemIndices: Joi.boolean().default(false), // show/hide indices in listing timeRange: Joi.object({ min: Joi.date().required(), max: Joi.date().required() @@ -34,38 +35,19 @@ export function esIndicesRoute(server) { }, async handler(req, reply) { const config = server.config(); - const ccs = req.payload.ccs; - const clusterUuid = req.params.clusterUuid; - const showSystemIndices = req.payload.showSystemIndices; + const { clusterUuid } = req.params; + const { show_system_indices: showSystemIndices } = req.query; + const { ccs } = req.payload; const esIndexPattern = prefixIndexPattern(config, 'xpack.monitoring.elasticsearch.index_pattern', ccs); try { const clusterStats = await getClusterStats(req, esIndexPattern, clusterUuid); const shardStats = await getShardStats(req, esIndexPattern, clusterStats, { includeIndices: true }); - const rows = await getIndices(req, esIndexPattern, showSystemIndices); - - const mappedRows = rows.map(row => { - const { name } = row; - const shardStatsForIndex = get(shardStats, ['indices', name]); - - if (shardStatsForIndex && shardStatsForIndex.status) { - return { - ...row, - status: shardStatsForIndex.status, - unassigned_shards: getUnassignedShards(shardStatsForIndex), - }; - } - - // not in shardStats docs, is a deleted index - return { - name, - status: 'Deleted' - }; - }); + const indices = await getIndices(req, esIndexPattern, showSystemIndices, shardStats); reply({ clusterStatus: getClusterStatus(clusterStats, shardStats), - rows: mappedRows + indices }); } catch(err) { reply(handleError(err, req)); diff --git a/x-pack/plugins/notifications/config.js b/x-pack/plugins/notifications/config.js new file mode 100644 index 00000000000000..9234e6ee5f2259 --- /dev/null +++ b/x-pack/plugins/notifications/config.js @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** + * User-configurable settings for xpack.notifications via configuration schema + * + * @param {Object} Joi - HapiJS Joi module that allows for schema validation + * @return {Object} config schema + */ +export const config = (Joi) => { + const { array, boolean, number, object, string } = Joi; + + return object({ + enabled: boolean().default(true), + email: object({ + enabled: boolean().default(false), + smtp: object({ + host: string().default('localhost'), + port: number().default(25), + require_tls: boolean().default(false), + pool: boolean().default(false), + auth: object({ + username: string(), + password: string() + }).default(), + }).default(), + defaults: object({ + from: string(), + to: array().single().items(string()), + cc: array().single().items(string()), + bcc: array().single().items(string()), + }).default(), + }).default(), + slack: object({ + enabled: boolean().default(false), + token: string().required(), + defaults: object({ + channel: string(), + as_user: boolean().default(false), + icon_emoji: string(), + icon_url: string(), + link_names: boolean().default(true), + mrkdwn: boolean().default(true), + unfurl_links: boolean().default(true), + unfurl_media: boolean().default(true), + username: string(), + }).default(), + }) + }).default(); +}; diff --git a/x-pack/plugins/notifications/index.js b/x-pack/plugins/notifications/index.js new file mode 100644 index 00000000000000..e6de33e9685e0e --- /dev/null +++ b/x-pack/plugins/notifications/index.js @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { resolve } from 'path'; +import { init } from './init'; +import { config } from './config'; + +/** + * Invokes plugin modules to instantiate the Notification plugin for Kibana + * + * @param kibana {Object} Kibana plugin instance + * @return {Object} Notification Kibana plugin object + */ +export const notifications = (kibana) => new kibana.Plugin({ + require: ['kibana', 'xpack_main'], + id: 'notifications', + configPrefix: 'xpack.notifications', + publicDir: resolve(__dirname, 'public'), + init, + config, +}); diff --git a/x-pack/plugins/notifications/init.js b/x-pack/plugins/notifications/init.js new file mode 100644 index 00000000000000..67c34b336f7373 --- /dev/null +++ b/x-pack/plugins/notifications/init.js @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + notificationService, + createEmailAction, + createSlackAction, + LoggerAction, +} from './server'; +import { notificationServiceSendRoute } from './server/routes/api/v1/notifications'; + +/** + * Initialize the Action Service with various actions provided by X-Pack, when configured. + * + * @param server {Object} HapiJS server instance + */ +export function init(server) { + const config = server.config(); + + // the logger + notificationService.setAction(new LoggerAction({ server })); + + if (config.get('xpack.notifications.email.enabled')) { + notificationService.setAction(createEmailAction(server)); + } + + if (config.get('xpack.notifications.slack.enabled')) { + notificationService.setAction(createSlackAction(server)); + } + + notificationServiceSendRoute(server, notificationService); + + // expose the notification service for other plugins + server.expose('notificationService', notificationService); +} diff --git a/x-pack/plugins/notifications/server/email/create_email_action.js b/x-pack/plugins/notifications/server/email/create_email_action.js new file mode 100644 index 00000000000000..5e3b63e4b7cd36 --- /dev/null +++ b/x-pack/plugins/notifications/server/email/create_email_action.js @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EmailAction } from './email_action'; + +/** + * Create a Nodemailer transporter options object from the config. + * + * @param {Object} config The server configuration. + * @return {Object} An object that configures Nodemailer. + */ +export function optionsFromConfig(config) { + return { + host: config.get('xpack.notifications.email.smtp.host'), + port: config.get('xpack.notifications.email.smtp.port'), + requireTLS: config.get('xpack.notifications.email.smtp.require_tls'), + pool: config.get('xpack.notifications.email.smtp.pool'), + auth: { + user: config.get('xpack.notifications.email.smtp.auth.username'), + pass: config.get('xpack.notifications.email.smtp.auth.password'), + }, + }; +} + +/** + * Create a Nodemailer defaults object from the config. + * + * Defaults include things like the default "from" email address. + * + * @param {Object} config The server configuration. + * @return {Object} An object that configures Nodemailer on a per-message basis. + */ +export function defaultsFromConfig(config) { + return { + from: config.get('xpack.notifications.email.defaults.from'), + to: config.get('xpack.notifications.email.defaults.to'), + cc: config.get('xpack.notifications.email.defaults.cc'), + bcc: config.get('xpack.notifications.email.defaults.bcc'), + }; +} + +/** + * Create a new Email Action based on the configuration. + * + * @param {Object} server The server object. + * @return {EmailAction} A new email action based on the kibana.yml configuration. + */ +export function createEmailAction(server, { _options = optionsFromConfig, _defaults = defaultsFromConfig } = { }) { + const config = server.config(); + + const options = _options(config); + const defaults = _defaults(config); + + return new EmailAction({ server, options, defaults }); +} diff --git a/x-pack/plugins/notifications/server/email/create_email_action.test.js b/x-pack/plugins/notifications/server/email/create_email_action.test.js new file mode 100644 index 00000000000000..fb9d46cdbe71ef --- /dev/null +++ b/x-pack/plugins/notifications/server/email/create_email_action.test.js @@ -0,0 +1,96 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EmailAction } from './email_action'; +import { + createEmailAction, + defaultsFromConfig, + optionsFromConfig, +} from './create_email_action'; + +describe('create_email_action', () => { + + test('optionsFromConfig uses config without modification', () => { + const get = key => { + const suffixes = [ + 'host', + 'port', + 'require_tls', + 'pool', + 'auth.username', + 'auth.password', + ]; + const value = suffixes.find(suffix => { + return `xpack.notifications.email.smtp.${suffix}` === key; + }); + + if (value === undefined) { + throw new Error(`Unknown config key used ${key}`); + } + + return value; + }; + + expect(optionsFromConfig({ get })).toEqual({ + host: 'host', + port: 'port', + requireTLS: 'require_tls', + pool: 'pool', + auth: { + user: 'auth.username', + pass: 'auth.password', + }, + }); + }); + + test('defaultsFromConfig uses config without modification', () => { + const get = key => { + const suffixes = [ + 'from', + 'to', + 'cc', + 'bcc', + ]; + const value = suffixes.find(suffix => { + return `xpack.notifications.email.defaults.${suffix}` === key; + }); + + if (value === undefined) { + throw new Error(`Unknown config key used ${key}`); + } + + return value; + }; + + expect(defaultsFromConfig({ get })).toEqual({ + from: 'from', + to: 'to', + cc: 'cc', + bcc: 'bcc', + }); + }); + + test('createEmailAction', async () => { + const config = { }; + const server = { config: jest.fn().mockReturnValue(config) }; + const _options = jest.fn().mockReturnValue({ options: true }); + const defaults = { defaults: true }; + const _defaults = jest.fn().mockReturnValue(defaults); + + const action = createEmailAction(server, { _options, _defaults }); + + expect(action instanceof EmailAction).toBe(true); + expect(action.defaults).toBe(defaults); + + expect(server.config).toHaveBeenCalledTimes(1); + expect(server.config).toHaveBeenCalledWith(); + expect(_options).toHaveBeenCalledTimes(1); + expect(_options).toHaveBeenCalledWith(config); + expect(_defaults).toHaveBeenCalledTimes(1); + expect(_defaults).toHaveBeenCalledWith(config); + }); + +}); diff --git a/x-pack/plugins/notifications/server/email/email_action.js b/x-pack/plugins/notifications/server/email/email_action.js new file mode 100644 index 00000000000000..a30b88a798d272 --- /dev/null +++ b/x-pack/plugins/notifications/server/email/email_action.js @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import nodemailer from 'nodemailer'; + +import { Action, ActionResult } from '../'; + +export const EMAIL_ACTION_ID = 'xpack-notifications-email'; + +/** + * Email Action enables generic sending of emails, when configured. + */ +export class EmailAction extends Action { + + /** + * Create a new Action capable of sending emails. + * + * @param {Object} server Kibana server object. + * @param {Object} options Configuration options for Nodemailer. + * @param {Object} defaults Default fields used when sending emails. + * @param {Object} _nodemailer Exposed for tests. + */ + constructor({ server, options, defaults = { }, _nodemailer = nodemailer }) { + super({ server, id: EMAIL_ACTION_ID, name: 'Email' }); + + this.transporter = _nodemailer.createTransport(options, defaults); + this.defaults = defaults; + } + + getMissingFields(notification) { + const missingFields = []; + + if (!Boolean(this.defaults.to) && !Boolean(notification.to)) { + missingFields.push({ + field: 'to', + name: 'To', + type: 'email', + }); + } + + if (!Boolean(this.defaults.from) && !Boolean(notification.from)) { + missingFields.push({ + field: 'from', + name: 'From', + type: 'email', + }); + } + + if (!Boolean(notification.subject)) { + missingFields.push({ + field: 'subject', + name: 'Subject', + type: 'text', + }); + } + + if (!Boolean(notification.markdown)) { + missingFields.push({ + field: 'markdown', + name: 'Body', + type: 'markdown', + }); + } + + return missingFields; + } + + async doPerformHealthCheck() { + // this responds with a boolean 'true' response, otherwise throws an Error + const response = await this.transporter.verify(); + + return new ActionResult({ + message: `Email action SMTP configuration has been verified.`, + response: { + verified: response + }, + }); + } + + async doPerformAction(notification) { + // Note: This throws an Error upon failure + const response = await this.transporter.sendMail({ + // email routing + from: notification.from, + to: notification.to, + cc: notification.cc, + bcc: notification.bcc, + // email content + subject: notification.subject, + html: notification.markdown, + text: notification.markdown, + }); + + return new ActionResult({ + message: `Sent email for '${notification.subject}'.`, + response, + }); + } + +} diff --git a/x-pack/plugins/notifications/server/email/email_action.test.js b/x-pack/plugins/notifications/server/email/email_action.test.js new file mode 100644 index 00000000000000..90ef5a3f59a780 --- /dev/null +++ b/x-pack/plugins/notifications/server/email/email_action.test.js @@ -0,0 +1,166 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ActionResult } from '../'; +import { EMAIL_ACTION_ID, EmailAction } from './email_action'; + +describe('EmailAction', () => { + + const server = { }; + const options = { options: true }; + const defaults = { defaults: true }; + const transporter = { + // see beforeEach + }; + const _nodemailer = { + // see beforeEach + }; + + let action; + + beforeEach(() => { + transporter.verify = jest.fn(); + transporter.sendMail = jest.fn(); + _nodemailer.createTransport = jest.fn().mockReturnValue(transporter); + + action = new EmailAction({ server, options, defaults, _nodemailer }); + }); + + test('id and name to be from constructor', () => { + expect(action.getId()).toBe(EMAIL_ACTION_ID); + expect(action.getName()).toBe('Email'); + expect(action.transporter).toBe(transporter); + + expect(_nodemailer.createTransport).toHaveBeenCalledTimes(1); + expect(_nodemailer.createTransport).toHaveBeenCalledWith(options, defaults); + }); + + describe('getMissingFields', () => { + + test('returns missing fields', () => { + const to = { field: 'to', name: 'To', type: 'email' }; + const from = { field: 'from', name: 'From', type: 'email' }; + const subject = { field: 'subject', name: 'Subject', type: 'text' }; + const markdown = { field: 'markdown', name: 'Body', type: 'markdown' }; + + const missing = [ + { defaults: { }, notification: { }, missing: [ to, from, subject, markdown, ], }, + { defaults: { }, notification: { from: 'b@c.co', subject: 'subject', markdown: 'body', }, missing: [ to, ], }, + { defaults: { from: 'b@c.co', }, notification: { subject: 'subject', markdown: 'body', }, missing: [ to, ], }, + { defaults: { }, notification: { to: 'a@b.co', subject: 'subject', markdown: 'body', }, missing: [ from, ], }, + { defaults: { to: 'a@b.co', }, notification: { subject: 'subject', markdown: 'body', }, missing: [ from, ], }, + { defaults: { }, notification: { to: 'a@b.co', from: 'b@c.co', markdown: 'body', }, missing: [ subject, ], }, + { defaults: { }, notification: { to: 'a@b.co', from: 'b@c.co', subject: 'subject', }, missing: [ markdown, ], }, + ]; + + missing.forEach(check => { + const newDefaultsAction = new EmailAction({ server, defaults: check.defaults, _nodemailer }); + + expect(newDefaultsAction.getMissingFields(check.notification)).toEqual(check.missing); + }); + }); + + test('returns [] when all fields exist', () => { + const exists = [ + { defaults: { }, notification: { to: 'a@b.co', from: 'b@c.co', subject: 'subject', markdown: 'body', }, }, + { defaults: { to: 'a@b.co', }, notification: { from: 'b@c.co', subject: 'subject', markdown: 'body', }, }, + { defaults: { from: 'b@c.co', }, notification: { to: 'a@b.co', subject: 'subject', markdown: 'body', }, }, + { defaults: { to: 'a@b.co', from: 'b@c.co', }, notification: { subject: 'subject', markdown: 'body', }, }, + ]; + + exists.forEach(check => { + const newDefaultsAction = new EmailAction({ server, defaults: check.defaults, _nodemailer }); + + expect(newDefaultsAction.getMissingFields(check.notification)).toEqual([]); + }); + }); + + }); + + describe('doPerformHealthCheck', () => { + + test('rethrows Error for failure', async () => { + const error = new Error('TEST - expected'); + + transporter.verify.mockRejectedValue(error); + + await expect(action.doPerformHealthCheck()) + .rejects + .toThrow(error); + + expect(transporter.verify).toHaveBeenCalledTimes(1); + expect(transporter.verify).toHaveBeenCalledWith(); + }); + + test('returns ActionResult for success', async () => { + transporter.verify.mockResolvedValue(true); + + const result = await action.doPerformHealthCheck(); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(true); + expect(result.getMessage()).toMatch('Email action SMTP configuration has been verified.'); + expect(result.getResponse()).toEqual({ + verified: true + }); + + expect(transporter.verify).toHaveBeenCalledTimes(1); + expect(transporter.verify).toHaveBeenCalledWith(); + }); + + }); + + describe('doPerformAction', () => { + const email = { subject: 'email', markdown: 'body' }; + + test('rethrows Error for failure', async () => { + const error = new Error('TEST - expected'); + + transporter.sendMail.mockRejectedValue(error); + + await expect(action.doPerformAction(email)) + .rejects + .toThrow(error); + + expect(transporter.sendMail).toHaveBeenCalledTimes(1); + expect(transporter.sendMail).toHaveBeenCalledWith({ + to: undefined, + from: undefined, + cc: undefined, + bcc: undefined, + subject: email.subject, + html: email.markdown, + text: email.markdown, + }); + }); + + test('returns ActionResult for success', async () => { + const response = { fake: true }; + + transporter.sendMail.mockResolvedValue(response); + + const result = await action.doPerformAction(email); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(true); + expect(result.getMessage()).toMatch(`Sent email for '${email.subject}'.`); + expect(result.getResponse()).toBe(response); + + expect(transporter.sendMail).toHaveBeenCalledTimes(1); + expect(transporter.sendMail).toHaveBeenCalledWith({ + to: undefined, + from: undefined, + cc: undefined, + bcc: undefined, + subject: email.subject, + html: email.markdown, + text: email.markdown, + }); + }); + + }); + +}); diff --git a/x-pack/plugins/notifications/server/email/index.js b/x-pack/plugins/notifications/server/email/index.js new file mode 100644 index 00000000000000..ff784e71bab738 --- /dev/null +++ b/x-pack/plugins/notifications/server/email/index.js @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { createEmailAction } from './create_email_action'; diff --git a/x-pack/plugins/notifications/server/index.js b/x-pack/plugins/notifications/server/index.js new file mode 100644 index 00000000000000..d877b5bb704301 --- /dev/null +++ b/x-pack/plugins/notifications/server/index.js @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { + notificationService, + Action, + ActionResult, +} from './service'; +export { createEmailAction } from './email'; +export { createSlackAction } from './slack'; +export { LoggerAction } from './logger'; diff --git a/x-pack/plugins/notifications/server/logger/index.js b/x-pack/plugins/notifications/server/logger/index.js new file mode 100644 index 00000000000000..c9d4686ad4ef38 --- /dev/null +++ b/x-pack/plugins/notifications/server/logger/index.js @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { LoggerAction } from './logger_action'; diff --git a/x-pack/plugins/notifications/server/logger/logger_action.js b/x-pack/plugins/notifications/server/logger/logger_action.js new file mode 100644 index 00000000000000..189f3638677cbc --- /dev/null +++ b/x-pack/plugins/notifications/server/logger/logger_action.js @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Action, ActionResult } from '../'; + +export const LOGGER_ACTION_ID = 'xpack-notifications-logger'; + +/** + * Logger Action enables generic logging of information into Kibana's logs. + * + * This is mostly useful for debugging. + */ +export class LoggerAction extends Action { + + constructor({ server }) { + super({ server, id: LOGGER_ACTION_ID, name: 'Log' }); + } + + getMissingFields() { + return []; + } + + async doPerformHealthCheck() { + return new ActionResult({ + message: `Logger action is always usable.`, + response: { }, + }); + } + + async doPerformAction(notification) { + this.server.log([LOGGER_ACTION_ID, 'info'], notification); + + return new ActionResult({ + message: 'Logged data returned as response.', + response: notification + }); + } + +} diff --git a/x-pack/plugins/notifications/server/logger/logger_action.test.js b/x-pack/plugins/notifications/server/logger/logger_action.test.js new file mode 100644 index 00000000000000..894399c0dc8bdc --- /dev/null +++ b/x-pack/plugins/notifications/server/logger/logger_action.test.js @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ActionResult } from '../'; +import { LOGGER_ACTION_ID, LoggerAction } from './logger_action'; + +describe('LoggerAction', () => { + + const action = new LoggerAction({ server: { } }); + + test('id and name to be from constructor', () => { + expect(action.id).toBe(LOGGER_ACTION_ID); + expect(action.name).toBe('Log'); + }); + + test('getMissingFields to return []', () => { + expect(action.getMissingFields()).toEqual([]); + }); + + test('doPerformHealthCheck returns ActionResult', async () => { + const result = await action.doPerformHealthCheck(); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(true); + expect(result.getMessage()).toMatch('Logger action is always usable.'); + expect(result.getResponse()).toEqual({ }); + }); + + test('doPerformAction logs and returns ActionResult', async () => { + const notification = { fake: true }; + + const logger = jest.fn(); + const server = { log: logger }; + const action = new LoggerAction({ server }); + + const result = await action.doPerformAction(notification); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(true); + expect(result.getMessage()).toMatch('Logged data returned as response.'); + expect(result.getResponse()).toBe(notification); + + expect(logger).toHaveBeenCalledTimes(1); + expect(logger).toHaveBeenCalledWith([LOGGER_ACTION_ID, 'info'], notification); + }); + +}); diff --git a/x-pack/plugins/notifications/server/routes/api/v1/notifications/index.js b/x-pack/plugins/notifications/server/routes/api/v1/notifications/index.js new file mode 100644 index 00000000000000..dd754c454ee254 --- /dev/null +++ b/x-pack/plugins/notifications/server/routes/api/v1/notifications/index.js @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { notificationServiceSendRoute } from './notify'; diff --git a/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.js b/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.js new file mode 100644 index 00000000000000..ad11190729ef3f --- /dev/null +++ b/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.js @@ -0,0 +1,108 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import Joi from 'joi'; +import { wrap } from 'boom'; + +/** + * Check the incoming request parameters to see if the action should be allowed to fire. + * + * @param {Object|null} action The action selected by the user. + * @param {String} actionId The ID of the requested action from the user. + * @param {Object} data The incoming data from the user. + * @returns {Object|null} The error object, or null if no error. + */ +export function checkForErrors(action, actionId, data) { + if (action === null) { + return { + message: `Unrecognized action: '${actionId}'.`, + }; + } else { + let validLicense = false; + + try { + validLicense = action.isLicenseValid(); + } catch (e) { + // validLicense === false + } + + if (validLicense === false) { + return { + message: `Unable to perform '${action.name}' action due to the current license.`, + }; + } + } + + const fields = action.getMissingFields(data); + + if (fields.length !== 0) { + return { + message: `Unable to perform '${action.name}' action due to missing required fields.`, + fields + }; + } + + return null; +} + +/** + * Attempt to send the {@code data} as a notification. + * + * @param {Object} server Kibana server object. + * @param {NotificationService} notificationService The notification service singleton. + * @param {String} actionId The specified action's ID. + * @param {Function} data The notification data to send via the specified action. + * @param {Function} reply The response function from the server route. + * @param {Function} _checkForErrors Exposed for testing. + */ +export async function sendNotification(server, notificationService, actionId, data, reply, { _checkForErrors = checkForErrors } = { }) { + const action = notificationService.getActionForId(actionId); + const error = _checkForErrors(action, actionId, data); + + if (error === null) { + return action.performAction(data) + .then(result => reply(result.toJson())) + .catch(err => reply(wrap(err))); // by API definition, this should never happen as performAction isn't allow to throw errrors + } + + server.log(['actions', 'error'], error.message); + + reply({ + status_code: 400, + ok: false, + message: `Error: ${error.message}`, + error, + }); +} + +/** + * Notification Service route to perform actions (aka send data). + */ +export function notificationServiceSendRoute(server, notificationService) { + server.route({ + method: 'POST', + path: '/api/notifications/v1/notify', + config: { + validate: { + payload: Joi.object({ + action: Joi.string().required(), + data: Joi.object({ + from: Joi.string(), + to: Joi.string(), + subject: Joi.string().required(), + markdown: Joi.string(), + }).required() + }) + } + }, + handler: (req, reply) => { + const actionId = req.payload.action; + const data = req.payload.data; + + sendNotification(server, notificationService, actionId, data, reply); + }, + }); +} diff --git a/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.test.js b/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.test.js new file mode 100644 index 00000000000000..55e272b38ce4a8 --- /dev/null +++ b/x-pack/plugins/notifications/server/routes/api/v1/notifications/notify.test.js @@ -0,0 +1,170 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { checkForErrors, sendNotification } from './notify'; +import { wrap } from 'boom'; + +describe('notifications/routes/send', () => { + + const id = 'notifications-test'; + const notification = { fake: true }; + + describe('checkForErrors', () => { + + it('returns unrecognized action for null action', () => { + expect(checkForErrors(null, id, { })).toEqual({ + message: `Unrecognized action: '${id}'.`, + }); + }); + + it('returns invalid license if license check throws an error', () => { + const action = { + name: 'Test Action', + isLicenseValid: () => { + throw new Error(); + }, + }; + + expect(checkForErrors(action, id, { })).toEqual({ + message: `Unable to perform '${action.name}' action due to the current license.`, + }); + }); + + it('returns invalid license if license is invalid', () => { + const action = { + name: 'Test Action', + isLicenseValid: () => false, + }; + + expect(checkForErrors(action, id, { })).toEqual({ + message: `Unable to perform '${action.name}' action due to the current license.`, + }); + }); + + it('returns fields related to missing data', () => { + const fields = [ { field: 1 } ]; + const action = { + name: 'Test Action', + isLicenseValid: () => true, + getMissingFields: (data) => { + expect(data).toBe(notification); + + return fields; + }, + }; + + const error = checkForErrors(action, id, notification); + + expect(error).toEqual({ + message: `Unable to perform '${action.name}' action due to missing required fields.`, + fields + }); + }); + + it('returns null if action is usable', () => { + const notification = { fake: true }; + const action = { + name: 'Test Action', + isLicenseValid: () => true, + getMissingFields: (data) => { + expect(data).toBe(notification); + + return []; + }, + }; + + expect(checkForErrors(action, id, notification)).toBeNull(); + }); + + }); + + describe('sendNotification', () => { + + it('replies with error object for bad request', async () => { + const error = { + message: 'TEST - expected', + fields: [ { fake: 1 } ], + }; + const action = { }; + const server = { + log: jest.fn(), + }; + const notificationService = { + getActionForId: jest.fn().mockReturnValue(action), + }; + const checkForErrors = jest.fn().mockReturnValue(error); + const reply = jest.fn(); + + await sendNotification(server, notificationService, id, notification, reply, { _checkForErrors: checkForErrors }); + + expect(notificationService.getActionForId).toHaveBeenCalledTimes(1); + expect(notificationService.getActionForId).toHaveBeenCalledWith(id); + expect(checkForErrors).toHaveBeenCalledTimes(1); + expect(checkForErrors).toHaveBeenCalledWith(action, id, notification); + expect(server.log).toHaveBeenCalledTimes(1); + expect(server.log).toHaveBeenCalledWith(['actions', 'error'], error.message); + + expect(reply).toHaveBeenCalledTimes(1); + expect(reply).toHaveBeenCalledWith({ + status_code: 400, + ok: false, + message: `Error: ${error.message}`, + error, + }); + }); + + it('replies with action result JSON', async () => { + const response = { ok: true, message: 'Test' }; + const result = { + toJson: () => response, + }; + const action = { + performAction: jest.fn().mockReturnValue(Promise.resolve(result)) + }; + const server = { }; + const notificationService = { + getActionForId: jest.fn().mockReturnValue(action), + }; + const checkForErrors = jest.fn().mockReturnValue(null); + const reply = jest.fn(); + + await sendNotification(server, notificationService, id, notification, reply, { _checkForErrors: checkForErrors }); + + expect(notificationService.getActionForId).toHaveBeenCalledTimes(1); + expect(notificationService.getActionForId).toHaveBeenCalledWith(id); + expect(checkForErrors).toHaveBeenCalledTimes(1); + expect(checkForErrors).toHaveBeenCalledWith(action, id, notification); + + expect(reply).toHaveBeenCalledTimes(1); + expect(reply).toHaveBeenCalledWith(response); + }); + + it('replies with unexpected result error', async () => { + const error = new Error(); + const action = { + performAction: jest.fn().mockReturnValue(Promise.reject(error)) + }; + const server = { }; + const notificationService = { + getActionForId: jest.fn().mockReturnValue(action), + }; + const checkForErrors = jest.fn().mockReturnValue(null); + const reply = jest.fn(); + + await sendNotification(server, notificationService, id, notification, reply, { _checkForErrors: checkForErrors }); + + expect(notificationService.getActionForId).toHaveBeenCalledTimes(1); + expect(notificationService.getActionForId).toHaveBeenCalledWith(id); + expect(checkForErrors).toHaveBeenCalledTimes(1); + expect(checkForErrors).toHaveBeenCalledWith(action, id, notification); + + expect(reply).toHaveBeenCalledTimes(1); + expect(reply).toHaveBeenCalledWith(wrap(error)); + }); + + }); + +}); diff --git a/x-pack/plugins/notifications/server/service/README.md b/x-pack/plugins/notifications/server/service/README.md new file mode 100644 index 00000000000000..3c8e77f3635277 --- /dev/null +++ b/x-pack/plugins/notifications/server/service/README.md @@ -0,0 +1,575 @@ +# Notification Service / Actions + +Use this service to send notifications to users. An example of a notification is sending an email or +explicitly adding something to the Kibana log. + +Notifications are inherently asynchronous actions because of the likelihood that any notification is +interacting with a remote server or service. + +## Referencing the Notification Service + +Note: Both of these may change in the future. + +### Server Side + +```js +const notificationService = server.plugins.notifications.notificationService; + +const action = notificationService.getActionForId('xpack-notifications-logger'); +const result = action.performAction({ + arbitrary: 'payload', + can: 'have multiple', + fields: [ 1, 2, 3 ] +}); +``` + +### HTTP + +```http +POST /api/notifications/v1/notify +{ + "action": "xpack-notifications-logger", + "data": { + "arbitrary": "payload", + "can": "have multiple", + "fields": [ 1, 2, 3 ] + } +} +``` + +## Interfaces + +There are two interfaces that are important from this package. `NotificationService`, which is exposed as +a singleton from the plugin: `server.plugins.notifications.notificationService`. And `Action`, which +provides an abstract Javascript `class` to implement new `Action`s. + +### NotificationService Interface + +The `NotificationService` currently has four methods defined with very distinct purposes: + +1. `setAction` is intended for plugin authors to add actions that do not exist with the basic notifications +service. +2. `removeAction` is intended for replacing existing plugins (e.g., augmenting another action). +3. `getActionForId` enables explicitly fetching an action by its known ID. +4. `getActionsForData` enables discovering compatible actions given an arbitrary set of data. + +Note: Mutating the Notification Service should generally only be done based on very specific reasons, +such as plugin initialization or the user dynamically configuring a service's availability (e.g., +if we support a secure data store, the user could theoretically provide authentication details for an email +server). + +It is also possible that the user will want to configure multiple variants of the same action, such as +multiple email notifications with differing defaults. In that case, the action's ID may need to be +reconsidered. + +#### `setAction()` + +This is the only way to add an `Action` instance. Instances are expected to be extensions of the `Action` +class defined here. If the provided action already exists, then the old one is removed. + +##### Syntax + +```js +notificationService.setAction(action); +``` + +###### Parameters + +| Field | Type | Description | +|-------|------|-------------| +| `action` | Action | The unique action to support. | + +###### Returns + +Nothing. + +##### Example + +Create a simple logging action that can be triggered generically. + +```js +class LoggerAction extends Action { + + constructor({ server }) { + super({ server, id: 'xpack-notifications-logger', name: 'Log' }); + } + + getMissingFields() { + return []; + } + + async doPerformHealthCheck() { + return new ActionResult({ + message: `Logger action is always usable.`, + response: { }, + }); + } + + async doPerformAction(notification) { + this.server.log(['logger', 'info'], notification); + + return new ActionResult({ + message: 'Logged data returned as response.', + response: notification + }); + } + +} + +// It's possible that someone may choose to make the LoggerAction's log level configurable, so +// replacing it could be done by re-setting it, which means any follow-on usage would use the new level +// (or, possibly, you could create different actions entirely for different levels) +notificationService.setAction(new LoggerAction({ server })); +``` + +#### `removeAction()` + +Remove an action that has been set. + +##### Syntax + +```js +const action = notificationService.removeAction(actionId); +``` + +###### Parameters + +| Field | Type | Description | +|-------|------|-------------| +| `id` | String | ID of the action to remove. | + +###### Returns + +| Type | Description | +|------|-------------| +| Action \| null | The action that was removed. `null` otherwise. | + +##### Example + +```js +const action = notificationService.removeAction('xpack-notifications-logger'); + +if (action !== null) { + // removed; otherwise it didn't exist (maybe it was already removed) +} +``` + +#### `getActionForId()` + +Retrieve a specific `Action` from the Notification Service. + +##### Syntax + +```js +const action = notificationService.getActionForId(actionId); +``` + +###### Parameters + +| Field | Type | Description | +|-------|------|-------------| +| `id` | String | ID of the action to retrieve. | + +###### Returns + +| Type | Description | +|------|-------------| +| Action \| null | The action that was requested. `null` otherwise. | + +##### Example + +```js +// In this case, the ID is known from the earlier example +const action = notificationService.getActionForId('xpack-notifications-logger'); + +if (action !== null) { + // otherwise it didn't exist +} +``` + +#### `getActionsForData()` + +Retrieve any `Action`s from the Notification Service that accept the supplied data, which is useful for +discovery. + +##### Syntax + +```js +const actions = notificationService.getActionsForData(notification); +``` + +###### Parameters + +| Field | Type | Description | +|-------|------|-------------| +| `notification` | Object | Payload to send notification. | + +###### Returns + +| Type | Description | +|------|-------------| +| Action[] | The actions that accept a subset of the data. Empty array otherwise. | + +##### Example + +```js +// In this case, the ID is known from the earlier example +const actions = notificationService.getActionsForData({ + arbitrary: 'payload', + can: 'have multiple', + fields: [ 1, 2, 3 ] +}); + +if (action.length !== 0) { + // otherwise nothing matches +} +``` + +### Action Interface + +From the perspective of developers that want to make use of `Action`s, there are three relevant methods: + +1. `getMissingFields` provides an array of fields as well as the expected data type that did not exist in the +supplied data. +2. `performHealthCheck` attempts to perform a health check against the actions backing service. +3. `performAction` attempts to perform the purpose of the action (e.g., send the email) using the supplied +data. + +For developers to create new `Action`s, there are three related methods: + +1. `getMissingFields` provides an array of fields as well as the expected data type that did not exist in the +supplied data. +2. `doPerformHealthCheck` attempts to perform a health check against the actions backing service. + - `performHealthCheck` invokes this method and wraps it in order to catch `Error`s. +3. `doPerformAction` attempts to perform the purpose of the action (e.g., send the email) using the supplied +data. + - `performAction` invokes this method and wraps it in order to catch `Error`s. + +Every method, excluding `getMissingFields`, is asynchronous. + +#### `getMissingFields()` + +This method enables the building of "Sharing"-style UIs that allow the same payload to be shared across +many different actions. This is the same approach taken in iOS and Android sharing frameworks. + +##### Syntax + +```js +action.getMissingFields({ + arbitrary: 'payload', + can: 'have multiple', + fields: [ 1, 2, 3 ] +}); +``` + +###### Parameters + +| Field | Type | Description | +|-------|------|-------------| +| `notification` | Object | The data that you want to try to use with the action. | + +###### Returns + +| Type | Description | +|------|-------------| +| Object[] | The fields that were not present in the `notification` object. Empty array otherwise. | + +The object definition should match: + +| Field | Type | Description | +|-------|------|-------------| +| `field` | String | The JSON field name that was expected. | +| `name` | String | The user-readable name of the field (e.g., for a generated UI). | +| `type` | String | The type of data (`email`, `text`, `markdown`, `number`, `date`, `boolean`). | + +NOTE: This method _never_ throws an `Error`. + +##### Example + +Create a simple action whose fields can be checked automatically. + +```js +// Action Users +const action = notificationService.getActionForId(actionId); +const fields = action.getMissingFields({ + arbitrary: 'payload', + can: 'have multiple', + fields: [ 1, 2, 3 ] +}); + +if (fields.length !== 0) { + // there's some fields missing so this action should not be used yet +} + +// Action Creators +class FakeAction extends Action { + + constructor({ server, defaults = { } }) { + super({ server, id: 'xpack-notifications-fake', name: 'Fake' }); + + this.defaults = defaults; + } + + getMissingFields(notification) { + const missingFields = []; + + if (!Boolean(this.defaults.to) && !Boolean(notification.to)) { + missingFields.push({ + field: 'to', + name: 'To', + type: 'email', + }); + } + + return missingFields; + } + + // ... other methods ... + +} +``` + +#### `performHealthCheck()` + +This method enables the health status of third party services to be polled. The current approach only allows +an `Action`'s health to be in a boolean state: either it's up and expected to work, or it's down. + +The health check is interesting because some third party services that we anticipate supporting are +inherently untrustworthy when it comes to supporting health checks (e.g., email servers). Therefore, it +should not be expected that the health check will block usage of actions -- only provide feedback to the +user, which we can ideally provide in a future notification center within the UI. + +##### Syntax + +```js +const result = await action.performHealthCheck(); +``` + +###### Parameters + +None. + +###### Returns + +| Type | Description | +|------|-------------| +| ActionResult | The result of the health check. | + +An `ActionResult` defines a few methods: + +| Method | Type | Description | +|-------|------|-------------| +| `isOk()` | Boolean | `true` if there was no error and it is believed to be "up". | +| `getError()` | Object \| undefined | JSON error object. | +| `getResponse()` | Object \| undefined | JSON response from the server. If the server returns a field, it should be wrapped. | +| `getMessage()` | String | Human readable message describing the state. | + +NOTE: This method _never_ throws an `Error`. + +##### Example + +Create a simple action whose fields can be checked automatically. + +```js +const action = notificationService.getActionForId(actionId); +const result = await action.performHealthCheck(); + +if (result.isOk()) { + // theoretically the action is in a usable state +} else { + // theoretically the action is not in a usable state (but some services may have broken health checks!) +} +``` + +#### `performAction()` + +This method enables the actual usage of the `Action` for action users. + +##### Syntax + +```js +const result = await action.performAction({ + arbitrary: 'payload', + can: 'have multiple', + fields: [ 1, 2, 3 ] +}); +``` + +###### Parameters + +| Field | Type | Description | +|-------|------|-------------| +| `notification` | Object | The data that you want to try to use with the action. | + +###### Returns + +| Type | Description | +|------|-------------| +| ActionResult | The result of the health check. | + +An `ActionResult` defines a few methods: + +| Method | Type | Description | +|-------|------|-------------| +| `isOk()` | Boolean | `true` if there was no error and it is believed to be "up". | +| `getError()` | Object \| undefined | JSON error object. | +| `getResponse()` | Object \| undefined | JSON response from the server. If the server returns a field, it should be wrapped. | +| `getMessage()` | String | Human readable message describing the state. | + +NOTE: This method _never_ throws an `Error`. + +##### Example + +Create a simple action whose fields can be checked automatically. + +```js +const action = notificationService.getActionForId(actionId); +const result = await action.performAction({ + arbitrary: 'payload', + can: 'have multiple', + fields: [ 1, 2, 3 ] +}); + +if (result.isOk()) { + // theoretically the action is in a usable state +} else { + // theoretically the action is not in a usable state (but some services may have broken health checks!) +} +``` + +#### `doPerformHealthCheck()` + +This method is for `Action` creators. This performs the actual work to check the health of the action's +associated service as best as possible. + +This method should be thought of as a `protected` method only and it should never be called directly +outside of tests. + +##### Syntax + +Do not call this method directly outside of tests. + +```js +const result = await action.doPerformHealthCheck(); +``` + +###### Parameters + +None. + +###### Returns + +| Type | Description | +|------|-------------| +| ActionResult | The result of the health check. | + +An `ActionResult` defines a few methods: + +| Method | Type | Description | +|-------|------|-------------| +| `isOk()` | Boolean | `true` if there was no error and it is believed to be "up". | +| `getError()` | Object \| undefined | JSON error object. | +| `getResponse()` | Object \| undefined | JSON response from the server. If the server returns a field, it should be wrapped. | +| `getMessage()` | String | Human readable message describing the state. | + +NOTE: This method can throw an `Error` in lieu of returning an `ActionResult`. + +##### Example + +Create a simple action whose health status can be checked automatically. + +```js +class FakeAction extends Action { + + constructor({ server }) { + super({ server, id: 'xpack-notifications-fake', name: 'Fake' }); + } + + async doPerformHealthCheck() { + // this responds with a boolean 'true' response, otherwise throws an Error + const response = await this.transporter.verify(); + + return new ActionResult({ + message: `Fake action configuration has been verified.`, + response: { + verified: true + }, + }); + } + + // ... other methods ... + +} +``` + +#### `doPerformAction()` + +This method is for `Action` creators. This performs the actual function of the action. + +This method should be thought of as a `protected` method only and it should never be called directly +outside of tests. + +##### Syntax + +Do not call this method directly outside of tests. + +```js +const result = await action.doPerformAction(); +``` + +###### Parameters + +| Field | Type | Description | +|-------|------|-------------| +| `notification` | Object | The data that you want to try to use with the action. | + +###### Returns + +| Type | Description | +|------|-------------| +| ActionResult | The result of the health check. | + +An `ActionResult` defines a few methods: + +| Method | Type | Description | +|-------|------|-------------| +| `isOk()` | Boolean | `true` if there was no error and it is believed to be "up". | +| `getError()` | Object \| undefined | JSON error object. | +| `getResponse()` | Object \| undefined | JSON response from the server. If the server returns a field, it should be wrapped. | +| `getMessage()` | String | Human readable message describing the state. | + +NOTE: This method can throw an `Error` in lieu of returning an `ActionResult`. + +##### Example + +Create a simple action whose health status can be checked automatically. + +```js +class FakeAction extends Action { + + constructor({ server }) { + super({ server, id: 'xpack-notifications-fake', name: 'Fake' }); + } + + async doPerformAction(notification) { + // Note: This throws an Error upon failure + const response = await this.transporter.sendMail({ + from: notification.from, + to: notification.to, + cc: notification.cc, + bcc: notification.bcc, + subject: notification.subject, + html: notification.markdown, + text: notification.markdown, + }); + + return new ActionResult({ + message: `Success! Sent email for '${notification.subject}'.`, + response, + }); + } + + // ... other methods ... + +} +``` diff --git a/x-pack/plugins/notifications/server/service/action.js b/x-pack/plugins/notifications/server/service/action.js new file mode 100644 index 00000000000000..6077ff6e2b41a9 --- /dev/null +++ b/x-pack/plugins/notifications/server/service/action.js @@ -0,0 +1,143 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ActionResult } from './action_result'; + +/** + * Actions represent a singular, generic "action", such as "Send to Email". + * + * Note: Implementations of Action are inherently server-side operations. It may or may not be desiable to fire + * these actions from the UI (triggering a server-side call), but these should be called for such a purpose. + */ +export class Action { + + /** + * Create a new Action. + * + * The suggested ID is the name of the plugin that provides it, and the unique portion. + * For example: "core-email" if core provided email. + * + * @param {Object} server The Kibana server object. + * @param {String} id The unique identifier for the action. + * @param {String} name User-friendly name for the action. + */ + constructor({ server, id, name }) { + this.server = server; + this.id = id; + this.name = name; + } + + /** + * Get the unique ID of the Action. + * + * @return {String} + */ + getId() { + return this.id; + } + + /** + * Get the user-friendly name of the Action. + * + * @return {String} + */ + getName() { + return this.name; + } + + /** + * Determine if this action can use the {@code notification}. This is useful if you use the action service + * generically, such as using it from a generic UI. + * + * This is intended to be a simple check of the {@code notification}, rather than an asynchronous action. + * + * @param {Object} notification The notification data to use. + * @return {Array} Array defining missing fields. Empty if none. + */ + getMissingFields() { + return []; + } + + /** + * Implementers must override to perform the health check. + * + * This should not be called directly outside of tests to ensure that any error is wrapped properly. + * + * Note: Some services do not provide consistent, reliable health checks, such as email. As such, + * implementers must weigh the nature of false negatives versus the utility of having this check. + * + * @return {Promise} The result of the health check, which must be an {@code ActionResult}. + * @throws {Error} if there is an unexpected failure occurs. + */ + async doPerformHealthCheck() { + throw new Error(`[doPerformHealthCheck] is not implemented for '${this.name}' action.`); + } + + /** + * Verify that the action can be used to the best of the ability of the service that it is using. + * + * @return {Promise} Always an {@code ActionResult}. + */ + async performHealthCheck() { + try { + return await this.doPerformHealthCheck(); + } catch (error) { + return new ActionResult({ + message: `Unable to perform '${this.name}' health check: ${error.message}.`, + error + }); + } + } + + /** + * Implementers must override to perform the action using the {@code notification}. + * + * This should not be called directly to ensure that any error is wrapped properly. + * + * @param {Object} notification The notification data to use. + * @return {Promise} The result of the action, which must be a {@code ActionResult}. + * @throws {Error} if the method is not implemented or an unexpected failure occurs. + */ + async doPerformAction(notification) { + throw new Error(`[doPerformAction] is not implemented for '${this.name}' action: ${JSON.stringify(notification)}`); + } + + /** + * Check to see if the current license allows actions. + * + * @return {Boolean} true when it is usable + * @throws {Error} if there is an unexpected issue checking the license + */ + isLicenseValid() { + return this.server.plugins.xpack_main.info.license.isNotBasic(); + } + + /** + * Perform the action using the {@code notification}. + * + * Actions automatically fail if the license check fails. + * + * Note to implementers: override doPerformAction instead of this method to help guarantee proper handling. + * + * @param {Object} notification The notification data to use. + * @return {Promise} The result of the action, which must be a {@code ActionResult}. + */ + async performAction(notification) { + try { + if (!this.isLicenseValid()) { + throw new Error(`The current license does not allow '${this.name}' action.`); + } + + return await this.doPerformAction(notification); + } catch (error) { + return new ActionResult({ + message: `Unable to perform '${this.name}' action: ${error.message}.`, + error + }); + } + } + +} diff --git a/x-pack/plugins/notifications/server/service/action.test.js b/x-pack/plugins/notifications/server/service/action.test.js new file mode 100644 index 00000000000000..a6fa5b28131318 --- /dev/null +++ b/x-pack/plugins/notifications/server/service/action.test.js @@ -0,0 +1,242 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Action } from './action'; +import { ActionResult } from './action_result'; + +describe('Action', () => { + + const server = { }; + const id = 'notifications-test'; + const unimplementedName = 'Unimplemented'; + const throwsErrorName = 'Throws Error'; + const passThruName = 'Test Action'; + const action = new Action({ server, id, name: unimplementedName }); + const notification = { + fake: true, + }; + + test('id and name to be from constructor', () => { + expect(action.server).toBe(server); + expect(action.getId()).toBe(id); + expect(action.getName()).toBe(unimplementedName); + }); + + test('getMissingFields returns an empty array', () => { + expect(action.getMissingFields()).toEqual([]); + expect(action.getMissingFields(notification)).toEqual([]); + }); + + test('doPerformHealthChecks throws error indicating that it is not implemented', async () => { + await expect(action.doPerformHealthCheck()) + .rejects + .toThrow(`[doPerformHealthCheck] is not implemented for '${unimplementedName}' action.`); + }); + + describe('performHealthChecks', () => { + + class ThrowsErrorHealthCheckAction extends Action { + constructor() { + super({ server: { }, id, name: throwsErrorName }); + } + + async doPerformHealthCheck() { + throw new Error('TEST - expected'); + } + } + + class PassThruHealthCheckAction extends Action { + constructor(result) { + super({ server: { }, id, name: passThruName }); + this.result = result; + } + + async doPerformHealthCheck() { + return this.result; + } + } + + test('runs against unimplemented doPerformHealthChecks', async () => { + const result = await action.performHealthCheck(); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(false); + expect(result.getMessage()) + .toMatch(new RegExp(`^Unable to perform '${unimplementedName}' health check: \\[doPerformHealthCheck\\] is not.*`)); + }); + + test('runs against failing doPerformHealthChecks', async () => { + const failAction = new ThrowsErrorHealthCheckAction(); + const result = await failAction.performHealthCheck(); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(false); + expect(result.getMessage()) + .toMatch(new RegExp(`^Unable to perform '${throwsErrorName}' health check: TEST - expected`)); + }); + + test('runs against succeeding result', async () => { + const expectedResult = new ActionResult({ message: 'Blah', response: { ok: true } }); + const succeedsAction = new PassThruHealthCheckAction(expectedResult); + const result = await succeedsAction.performHealthCheck(); + + expect(result).toBe(expectedResult); + }); + + }); + + test('doPerformAction throws error indicating that it is not implemented', async () => { + await expect(action.doPerformAction(notification)) + .rejects + .toThrow(`[doPerformAction] is not implemented for '${unimplementedName}' action: {"fake":true}`); + }); + + describe('isLicenseValid', () => { + + test('server variable is not exposed as expected', () => { + expect(() => action.isLicenseValid()).toThrow(Error); + }); + + test('returns false is license is not valid', () => { + const unlicensedServer = { + plugins: { + xpack_main: { + info: { + license: { + isNotBasic: () => false + } + } + } + } + }; + const unlicensedAction = new Action({ server: unlicensedServer, id, name: unimplementedName }); + + expect(unlicensedAction.isLicenseValid()).toBe(false); + }); + + test('returns true is license is not valid', () => { + const licensedServer = { + plugins: { + xpack_main: { + info: { + license: { + isNotBasic: () => true + } + } + } + } + }; + const licensedAction = new Action({ server: licensedServer, id, name: unimplementedName }); + + expect(licensedAction.isLicenseValid()).toBe(true); + }); + + }); + + describe('performAction', () => { + + // valid license + const server = { + plugins: { + xpack_main: { + info: { + license: { + isNotBasic: () => true + } + } + } + } + }; + + class ThrowsErrorAction extends Action { + constructor() { + super({ server, id, name: throwsErrorName }); + } + + async doPerformAction() { + throw new Error('TEST - expected'); + } + } + + class PassThruAction extends Action { + constructor(result) { + super({ server, id, name: passThruName }); + this.result = result; + } + + async doPerformAction() { + return this.result; + } + } + + describe('fails license check', () => { + + // handles the case when xpack_main definitions change + test('because of bad reference', async () => { + // server is an empty object, so a reference fails early in the chain (mostly a way to give devs a way to find this error) + const result = await action.performAction(notification); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(false); + }); + + test('because license is invalid or basic', async () => { + const unlicensedServer = { + plugins: { + xpack_main: { + info: { + license: { + isNotBasic: () => false + } + } + } + } + }; + const unlicensedAction = new Action({ server: unlicensedServer, id, name: unimplementedName }); + const result = await unlicensedAction.performAction(notification); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(false); + expect(result.getMessage()) + .toMatch( + `Unable to perform '${unimplementedName}' action: ` + + `The current license does not allow '${unimplementedName}' action.` + ); + }); + + }); + + test('runs against unimplemented doPerformAction', async () => { + const licensedAction = new Action({ server, id, name: unimplementedName }); + const result = await licensedAction.performAction(notification); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(false); + expect(result.getMessage()) + .toMatch(new RegExp(`^Unable to perform '${unimplementedName}' action: \\[doPerformAction\\] is not.*`)); + }); + + test('runs against failing doPerformAction', async () => { + const failAction = new ThrowsErrorAction(); + const result = await failAction.performAction(notification); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(false); + expect(result.getMessage()) + .toMatch(new RegExp(`^Unable to perform '${throwsErrorName}' action: TEST - expected`)); + }); + + test('runs against succeeding result', async () => { + const expectedResult = new ActionResult({ message: 'Blah', response: { ok: true } }); + const succeedsAction = new PassThruAction(expectedResult); + const result = await succeedsAction.performAction(notification); + + expect(result).toBe(expectedResult); + }); + + }); + +}); diff --git a/x-pack/plugins/notifications/server/service/action_result.js b/x-pack/plugins/notifications/server/service/action_result.js new file mode 100644 index 00000000000000..35507045c898ce --- /dev/null +++ b/x-pack/plugins/notifications/server/service/action_result.js @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** + * Action Results represent generic, predictable responses from Actions. + */ +export class ActionResult { + + /** + * Create a new Action Result. + * + * Success is determined by the existence of an error. + * + * @param {String} message The message to display about the result, presumably in a Toast. + * @param {Object|undefined} response The response from the "other" side. + * @param {Object|undefined} error The error, if any. + */ + constructor({ message, response, error }) { + this.message = message; + this.response = response; + this.error = error; + this.ok = !Boolean(error); + } + + /** + * Get the error caused by the action. + * + * @returns {Object|undefined} The error response, or {@code undefined} if no error. + */ + getError() { + return this.error; + } + + /** + * Get the message displayable to the user. + * + * @returns {String} The message. + */ + getMessage() { + return this.message; + } + + /** + * The raw JSON response from the action. + * + * @returns {Object|undefined} The JSON response. + */ + getResponse() { + return this.response; + } + + /** + * Determine if the action succeeded. + * + * @returns {Boolean} {@code true} for success. + */ + isOk() { + return this.ok; + } + + toJson() { + return { + ok: this.ok, + error: this.error, + message: this.message, + response: this.response, + }; + } + +} diff --git a/x-pack/plugins/notifications/server/service/action_result.test.js b/x-pack/plugins/notifications/server/service/action_result.test.js new file mode 100644 index 00000000000000..128ddb1dd8b92f --- /dev/null +++ b/x-pack/plugins/notifications/server/service/action_result.test.js @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ActionResult } from './action_result'; + +describe('ActionResult', () => { + + const message = 'this is a message'; + const response = { other: { side: { response: true } } }; + const error = { message: `Error: ${message}` }; + + const okResult = new ActionResult({ message, response }); + const notOkResult = new ActionResult({ message, response, error }); + + test('getError returns supplied error or undefined', () => { + expect(okResult.getError()).toBeUndefined(); + expect(notOkResult.getError()).toBe(error); + }); + + test('getMessage returns supplied message', () => { + expect(okResult.getMessage()).toBe(message); + expect(notOkResult.getMessage()).toBe(message); + }); + + test('getResponse returns supplied response', () => { + expect(okResult.getResponse()).toBe(response); + expect(notOkResult.getResponse()).toBe(response); + }); + + test('isOk returns based on having an error', () => { + expect(okResult.isOk()).toBe(true); + expect(notOkResult.isOk()).toBe(false); + }); + + test('toJson', () => { + expect(okResult.toJson()).toEqual({ + ok: true, + error: undefined, + message, + response, + }); + + expect(notOkResult.toJson()).toEqual({ + ok: false, + error, + message, + response, + }); + }); + +}); diff --git a/x-pack/plugins/notifications/server/service/index.js b/x-pack/plugins/notifications/server/service/index.js new file mode 100644 index 00000000000000..dd64e16abc7135 --- /dev/null +++ b/x-pack/plugins/notifications/server/service/index.js @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { notificationService } from './notification_service'; +export { Action } from './action'; +export { ActionResult } from './action_result'; diff --git a/x-pack/plugins/notifications/server/service/notification_service.js b/x-pack/plugins/notifications/server/service/notification_service.js new file mode 100644 index 00000000000000..5804532d8be68f --- /dev/null +++ b/x-pack/plugins/notifications/server/service/notification_service.js @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/** + * Notification Service represents a service that contains generic "actions", such as "Send to Email" + * that are added at startup by plugins to enable notifications to be sent either by the user manually + * or via the some scheduled / automated task. + */ +export class NotificationService { + + constructor() { + this.actions = []; + } + + /** + * Add a new action to the action service. + * + * @param {Action} action An implementation of Action. + */ + setAction = (action) => { + this.removeAction(action.id); + + this.actions.push(action); + } + + /** + * Remove an existing action from the action service. + * + * @param {String} id The ID of the action to remove. + * @return {Action} The action that was removed, or null. + */ + removeAction = (id) => { + const index = this.actions.findIndex(action => action.id === id); + + if (index !== -1) { + const removedActions = this.actions.splice(index, 1); + return removedActions[0]; + } + + return null; + } + + /** + * Get action with the specified {@code id}, if any. + * + * This is useful when you know that an action is provided, such as one provided by your own plugin, + * and you want to use it to handle things in a consistent way. + * + * @param {String} id The ID of the Action. + * @return {Action} The Action that matches the ID, or null. + */ + getActionForId = (id) => { + const index = this.actions.findIndex(action => action.id === id); + + if (index !== -1) { + return this.actions[index]; + } + + return null; + } + + /** + * Get actions that will accept the {@code data}. + * + * @param {Object} data The data object to pass to actions. + * @return {Array} An array of Actions that can be used with the data, if any. Empty if none. + */ + getActionsForData = (data) => { + return this.actions.filter(action => { + try { + return action.getMissingFields(data).length === 0; + } catch (err) { + return false; + } + }); + } + +} + +/** + * A singleton reference to the notification service intended to be used across Kibana. + */ +export const notificationService = new NotificationService(); diff --git a/x-pack/plugins/notifications/server/service/notification_service.test.js b/x-pack/plugins/notifications/server/service/notification_service.test.js new file mode 100644 index 00000000000000..903d7ea0c5d922 --- /dev/null +++ b/x-pack/plugins/notifications/server/service/notification_service.test.js @@ -0,0 +1,134 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Action } from './action'; +import { NotificationService } from './notification_service'; + +class TestAction extends Action { + constructor({ server, id }) { + super({ server, id, name: 'TestAction' }); + } + + getMissingFields() { + return []; + } +} + +// always returns a missing field +class MissingFieldTestAction extends Action { + constructor({ server, id }) { + super({ server, id, name: 'MissingFieldTestAction' }); + } + + getMissingFields() { + return [ { field: 'subject', name: 'Subject', type: 'text' } ]; + } +} + +describe('NotificationService', () => { + + const server = { }; + const actionId = 'notifications-test'; + const action = new TestAction({ server, id: actionId }); + + let notificationService; + + beforeEach(() => { + notificationService = new NotificationService(); + }); + + test('initializes with no default actions', () => { + expect(notificationService.actions).toEqual([]); + }); + + describe('setAction', () => { + + test('adds the action', () => { + notificationService.setAction(action); + + expect(notificationService.actions[0]).toBe(action); + }); + + test('removes any action with the same ID first, then adds the action', () => { + notificationService.setAction({ id: actionId }); + notificationService.setAction(action); + + expect(notificationService.actions).toHaveLength(1); + expect(notificationService.actions[0]).toBe(action); + }); + + }); + + describe('removeAction', () => { + + test('returns null if the action does not exist', () => { + expect(notificationService.removeAction(actionId)).toBe(null); + + notificationService.setAction(action); + + expect(notificationService.removeAction('not-' + actionId)).toBe(null); + expect(notificationService.actions[0]).toBe(action); + }); + + test('returns the removed action', () => { + notificationService.setAction(action); + + expect(notificationService.removeAction(actionId)).toBe(action); + expect(notificationService.actions).toEqual([]); + }); + + }); + + describe('getActionForId', () => { + + test('returns null if the action does not exist', () => { + expect(notificationService.getActionForId(actionId)).toBe(null); + + notificationService.setAction(action); + + expect(notificationService.getActionForId('not-' + actionId)).toBe(null); + expect(notificationService.actions[0]).toBe(action); + }); + + test('returns the action', () => { + notificationService.setAction(action); + + expect(notificationService.getActionForId(actionId)).toBe(action); + expect(notificationService.actions[0]).toBe(action); + }); + + }); + + describe('getActionsForData', () => { + + test('returns [] if no corresponding action exists', () => { + expect(notificationService.getActionsForData({})).toEqual([]); + + notificationService.setAction(new MissingFieldTestAction({ server, id: 'always-missing' })); + + expect(notificationService.getActionsForData({})).toEqual([]); + expect(notificationService.actions).toHaveLength(1); + }); + + test('returns the actions that match', () => { + notificationService.setAction(action); + + expect(notificationService.getActionsForData({})).toEqual([ action ]); + expect(notificationService.actions[0]).toBe(action); + + const otherActionId = 'other-' + actionId; + + notificationService.setAction(new MissingFieldTestAction({ server, id: 'always-missing' })); + notificationService.setAction(new TestAction({ server, id: otherActionId })); + + const actions = notificationService.getActionsForData({}); + + expect(actions.map(action => action.id)).toEqual([ actionId, otherActionId ]); + }); + + }); + +}); diff --git a/x-pack/plugins/notifications/server/slack/create_slack_action.js b/x-pack/plugins/notifications/server/slack/create_slack_action.js new file mode 100644 index 00000000000000..ecffcadc9b4dac --- /dev/null +++ b/x-pack/plugins/notifications/server/slack/create_slack_action.js @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SlackAction } from './slack_action'; + +/** + * Create a Slack options object from the config. + * + * @param {Object} config The server configuration. + * @return {Object} An object that configures Slack. + */ +export function optionsFromConfig(config) { + return { + token: config.get('xpack.notifications.slack.token') + }; +} + +/** + * Create a Slack defaults object from the config. + * + * Defaults include things like the default channel that messages are posted to. + * + * @param {Object} config The server configuration. + * @return {Object} An object that configures Slack on a per-message basis. + */ +export function defaultsFromConfig(config) { + return { + channel: config.get('xpack.notifications.slack.defaults.channel'), + as_user: config.get('xpack.notifications.slack.defaults.as_user'), + icon_emoji: config.get('xpack.notifications.slack.defaults.icon_emoji'), + icon_url: config.get('xpack.notifications.slack.defaults.icon_url'), + link_names: config.get('xpack.notifications.slack.defaults.link_names'), + mrkdwn: config.get('xpack.notifications.slack.defaults.mrkdwn'), + unfurl_links: config.get('xpack.notifications.slack.defaults.unfurl_links'), + unfurl_media: config.get('xpack.notifications.slack.defaults.unfurl_media'), + username: config.get('xpack.notifications.slack.defaults.username'), + }; +} + +/** + * Create a new Slack Action based on the configuration. + * + * @param {Object} server The server object. + * @return {SlackAction} A new Slack Action based on the kibana.yml configuration. + */ +export function createSlackAction(server, { _options = optionsFromConfig, _defaults = defaultsFromConfig } = { }) { + const config = server.config(); + + const options = _options(config); + const defaults = _defaults(config); + + return new SlackAction({ server, options, defaults }); +} diff --git a/x-pack/plugins/notifications/server/slack/create_slack_action.test.js b/x-pack/plugins/notifications/server/slack/create_slack_action.test.js new file mode 100644 index 00000000000000..68d669985568a9 --- /dev/null +++ b/x-pack/plugins/notifications/server/slack/create_slack_action.test.js @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SlackAction } from './slack_action'; +import { + createSlackAction, + defaultsFromConfig, + optionsFromConfig, +} from './create_slack_action'; + +describe('create_slack_action', () => { + + test('optionsFromConfig uses config without modification', () => { + const get = key => { + const suffixes = [ + 'token', + ]; + const value = suffixes.find(suffix => { + return `xpack.notifications.slack.${suffix}` === key; + }); + + if (value === undefined) { + throw new Error(`Unknown config key used ${key}`); + } + + return value; + }; + + expect(optionsFromConfig({ get })).toEqual({ + token: 'token', + }); + }); + + test('defaultsFromConfig uses config without modification', () => { + const get = key => { + const suffixes = [ + 'channel', + 'as_user', + 'icon_emoji', + 'icon_url', + 'link_names', + 'mrkdwn', + 'unfurl_links', + 'unfurl_media', + 'username', + ]; + const value = suffixes.find(suffix => { + return `xpack.notifications.slack.defaults.${suffix}` === key; + }); + + if (value === undefined) { + throw new Error(`Unknown config key used ${key}`); + } + + return value; + }; + + expect(defaultsFromConfig({ get })).toEqual({ + channel: 'channel', + as_user: 'as_user', + icon_emoji: 'icon_emoji', + icon_url: 'icon_url', + link_names: 'link_names', + mrkdwn: 'mrkdwn', + unfurl_links: 'unfurl_links', + unfurl_media: 'unfurl_media', + username: 'username', + }); + }); + + test('createSlackAction', async () => { + const config = { }; + const server = { config: jest.fn().mockReturnValue(config) }; + const _options = jest.fn().mockReturnValue({ options: true }); + const defaults = { defaults: true }; + const _defaults = jest.fn().mockReturnValue(defaults); + + const action = createSlackAction(server, { _options, _defaults }); + + expect(action instanceof SlackAction).toBe(true); + expect(action.defaults).toBe(defaults); + + expect(server.config).toHaveBeenCalledTimes(1); + expect(server.config).toHaveBeenCalledWith(); + expect(_options).toHaveBeenCalledTimes(1); + expect(_options).toHaveBeenCalledWith(config); + expect(_defaults).toHaveBeenCalledTimes(1); + expect(_defaults).toHaveBeenCalledWith(config); + }); + +}); diff --git a/x-pack/plugins/notifications/server/slack/index.js b/x-pack/plugins/notifications/server/slack/index.js new file mode 100644 index 00000000000000..da7cd204e88877 --- /dev/null +++ b/x-pack/plugins/notifications/server/slack/index.js @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { createSlackAction } from './create_slack_action'; diff --git a/x-pack/plugins/notifications/server/slack/slack_action.js b/x-pack/plugins/notifications/server/slack/slack_action.js new file mode 100644 index 00000000000000..236ce1af9c360b --- /dev/null +++ b/x-pack/plugins/notifications/server/slack/slack_action.js @@ -0,0 +1,116 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { WebClient } from '@slack/client'; + +import { Action, ActionResult } from '../'; + +export const SLACK_ACTION_ID = 'xpack-notifications-slack'; + +/** + * Create a new Slack {@code WebClient}. + * + * Currently the only option expected is {@code token}. + * + * @param {Object} options Slack API options. + * @returns {WebClient} Always. + */ +export function webClientCreator(options) { + return new WebClient(options.token); +} + +/** + * Slack Action enables generic sending of Slack messages. + */ +export class SlackAction extends Action { + + /** + * Create a new Action capable of sending Slack messages. + * + * @param {Object} server Kibana server object. + * @param {Object} options Configuration options for the Slack WebClient. Currently only expect "token" field. + * @param {Object} defaults Default fields used when sending messages. + * @param {Function} _webClientCreator Exposed for tests. + */ + constructor({ server, options, defaults = { }, _webClientCreator = webClientCreator }) { + super({ server, id: SLACK_ACTION_ID, name: 'Slack' }); + + this.client = _webClientCreator(options); + this.defaults = defaults; + } + + getMissingFields(data) { + const missingFields = []; + + if (!Boolean(this.defaults.channel) && !Boolean(data.channel)) { + missingFields.push({ + field: 'channel', + name: 'Channel', + type: 'text', + }); + } + + if (!Boolean(data.subject)) { + missingFields.push({ + field: 'subject', + name: 'Message', + type: 'markdown', + }); + } + + return missingFields; + } + + async doPerformHealthCheck() { + const response = await this.client.api.test(); + + if (response.ok) { + return new ActionResult({ + message: `Slack action configuration has been verified.`, + response, + }); + } + + return new ActionResult({ + message: `Slack action configuration could not be verified.`, + response, + error: response.error || { message: 'Unknown Error' }, + }); + } + + /** + * Render the message based on whether or not a {@code markdown} body was supplied. + */ + renderMessage({ subject, markdown }) { + const attachments = []; + + if (markdown) { + attachments.push({ text: markdown }); + } + + return { text: subject, attachments }; + } + + async doPerformAction({ subject, markdown, channel }) { + // NOTE: When we want to support files, then we should look into using client.files.upload({ ... }) + // without _also_ sending chat message because the file upload endpoint supports chat behavior + // in addition to files, but the reverse is not true. + const slackChannel = channel || this.defaults.channel; + + const response = await this.client.chat.postMessage({ + ...this.defaults, + ...this.renderMessage({ subject, markdown }), + channel: slackChannel, + }); + + return new ActionResult({ + message: `Posted Slack message to channel '${slackChannel}'.`, + response, + error: response.error, + }); + } + +} diff --git a/x-pack/plugins/notifications/server/slack/slack_action.test.js b/x-pack/plugins/notifications/server/slack/slack_action.test.js new file mode 100644 index 00000000000000..833047a580abb7 --- /dev/null +++ b/x-pack/plugins/notifications/server/slack/slack_action.test.js @@ -0,0 +1,277 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { WebClient } from '@slack/client'; +import { ActionResult } from '../'; +import { + SLACK_ACTION_ID, + SlackAction, + webClientCreator, +} from './slack_action'; + +describe('SlackAction', () => { + + const server = { }; + const options = { options: true }; + const defaults = { defaults: true }; + const client = { + api: { + // see beforeEach + }, + chat: { + // see beforeEach + } + }; + let _webClientCreator; + + let action; + + beforeEach(() => { + client.api.test = jest.fn(); + client.chat.postMessage = jest.fn(); + _webClientCreator = jest.fn().mockReturnValue(client); + + action = new SlackAction({ server, options, defaults, _webClientCreator }); + }); + + test('webClientCreator creates a WebClient', () => { + expect(webClientCreator('faketoken') instanceof WebClient).toBe(true); + }); + + test('id and name to be from constructor', () => { + expect(action.getId()).toBe(SLACK_ACTION_ID); + expect(action.getName()).toBe('Slack'); + expect(action.client).toBe(client); + + expect(_webClientCreator).toHaveBeenCalledTimes(1); + expect(_webClientCreator).toHaveBeenCalledWith(options); + }); + + describe('getMissingFields', () => { + + test('returns missing fields', () => { + const channel = { field: 'channel', name: 'Channel', type: 'text' }; + const subject = { field: 'subject', name: 'Message', type: 'markdown' }; + + const missing = [ + { defaults: { }, notification: { }, missing: [ channel, subject, ], }, + { defaults: { }, notification: { channel: '#kibana', }, missing: [ subject, ], }, + { defaults: { channel: '#kibana', }, notification: { }, missing: [ subject, ], }, + { defaults: { }, notification: { subject: 'subject', }, missing: [ channel, ], }, + ]; + + missing.forEach(check => { + const newDefaultsAction = new SlackAction({ server, options, defaults: check.defaults, _webClientCreator }); + + expect(newDefaultsAction.getMissingFields(check.notification)).toEqual(check.missing); + }); + }); + + test('returns [] when all fields exist', () => { + const exists = [ + { defaults: { }, notification: { channel: '#kibana', subject: 'subject', }, }, + { defaults: { channel: '#kibana', }, notification: { subject: 'subject', }, }, + ]; + + exists.forEach(check => { + const newDefaultsAction = new SlackAction({ server, options, defaults: check.defaults, _webClientCreator }); + + expect(newDefaultsAction.getMissingFields(check.notification)).toEqual([]); + }); + }); + + }); + + describe('doPerformHealthCheck', () => { + + test('rethrows Error for failure', async () => { + const error = new Error('TEST - expected'); + + client.api.test.mockRejectedValue(error); + + await expect(action.doPerformHealthCheck()) + .rejects + .toThrow(error); + + expect(client.api.test).toHaveBeenCalledTimes(1); + expect(client.api.test).toHaveBeenCalledWith(); + }); + + test('returns ActionResult if not ok with error', async () => { + const response = { ok: false, error: { expected: true } }; + + client.api.test.mockResolvedValue(response); + + const result = await action.doPerformHealthCheck(); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(false); + expect(result.getMessage()).toMatch('Slack action configuration could not be verified.'); + expect(result.getResponse()).toBe(response); + expect(result.getError()).toBe(response.error); + + expect(client.api.test).toHaveBeenCalledTimes(1); + expect(client.api.test).toHaveBeenCalledWith(); + }); + + test('returns ActionResult if not ok with default error', async () => { + const response = { ok: false }; + + client.api.test.mockResolvedValue(response); + + const result = await action.doPerformHealthCheck(); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(false); + expect(result.getMessage()).toMatch('Slack action configuration could not be verified.'); + expect(result.getResponse()).toBe(response); + expect(result.getError()).toEqual({ message: 'Unknown Error' }); + + expect(client.api.test).toHaveBeenCalledTimes(1); + expect(client.api.test).toHaveBeenCalledWith(); + }); + + test('returns ActionResult for success', async () => { + const response = { ok: true }; + + client.api.test.mockResolvedValue(response); + + const result = await action.doPerformHealthCheck(); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(true); + expect(result.getMessage()).toMatch('Slack action configuration has been verified.'); + expect(result.getResponse()).toBe(response); + + expect(client.api.test).toHaveBeenCalledTimes(1); + expect(client.api.test).toHaveBeenCalledWith(); + }); + + }); + + describe('renderMessage', () => { + + test('does not contain attachments', () => { + const message = { subject: 'subject' }; + const response = action.renderMessage(message); + + expect(response).toMatchObject({ + text: message.subject, + attachments: [ ] + }); + }); + + test('contains attachments', () => { + const message = { subject: 'subject', markdown: 'markdown' }; + const response = action.renderMessage(message); + + expect(response).toMatchObject({ + text: message.subject, + attachments: [ + { + text: message.markdown + } + ] + }); + }); + + }); + + describe('doPerformAction', () => { + const message = { channel: '#kibana', subject: 'subject', markdown: 'body', }; + + test('rethrows Error for failure', async () => { + const error = new Error('TEST - expected'); + + client.chat.postMessage.mockRejectedValue(error); + + await expect(action.doPerformAction(message)) + .rejects + .toThrow(error); + + expect(client.chat.postMessage).toHaveBeenCalledTimes(1); + expect(client.chat.postMessage).toHaveBeenCalledWith({ + ...defaults, + ...action.renderMessage(message), + channel: message.channel, + }); + }); + + test('returns ActionResult for failure without Error', async () => { + const response = { fake: true, error: { expected: true } }; + + client.chat.postMessage.mockResolvedValue(response); + + const result = await action.doPerformAction(message); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(false); + expect(result.getMessage()).toMatch(`Posted Slack message to channel '${message.channel}'.`); + expect(result.getResponse()).toBe(response); + expect(result.getError()).toBe(response.error); + + expect(client.chat.postMessage).toHaveBeenCalledTimes(1); + expect(client.chat.postMessage).toHaveBeenCalledWith({ + ...defaults, + ...action.renderMessage(message), + channel: message.channel, + }); + }); + + + test('returns ActionResult for success', async () => { + const response = { fake: true }; + + client.chat.postMessage.mockResolvedValue(response); + + const result = await action.doPerformAction(message); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(true); + expect(result.getMessage()).toMatch(`Posted Slack message to channel '${message.channel}'.`); + expect(result.getResponse()).toBe(response); + + expect(client.chat.postMessage).toHaveBeenCalledTimes(1); + expect(client.chat.postMessage).toHaveBeenCalledWith({ + ...defaults, + ...action.renderMessage(message), + channel: message.channel, + }); + }); + + test('returns ActionResult for success with default channel', async () => { + const response = { fake: false }; + + client.chat.postMessage.mockResolvedValue(response); + + const channelDefaults = { + ...defaults, + channel: '#kibana', + }; + const noChannelMessage = { + ...message, + channel: undefined, + }; + const newDefaultsAction = new SlackAction({ server, options, defaults: channelDefaults, _webClientCreator }); + + const result = await newDefaultsAction.doPerformAction(noChannelMessage); + + expect(result instanceof ActionResult).toBe(true); + expect(result.isOk()).toBe(true); + expect(result.getMessage()).toMatch(`Posted Slack message to channel '${channelDefaults.channel}'.`); + expect(result.getResponse()).toBe(response); + + expect(client.chat.postMessage).toHaveBeenCalledTimes(1); + expect(client.chat.postMessage).toHaveBeenCalledWith({ + ...defaults, + ...action.renderMessage(noChannelMessage), + channel: channelDefaults.channel, + }); + }); + + }); + +}); diff --git a/x-pack/plugins/reporting/common/constants.js b/x-pack/plugins/reporting/common/constants.js index 53f6e24af5ca0f..6376c44042e251 100644 --- a/x-pack/plugins/reporting/common/constants.js +++ b/x-pack/plugins/reporting/common/constants.js @@ -12,4 +12,10 @@ export const API_BASE_URL = '/api/reporting'; export const WHITELISTED_JOB_CONTENT_TYPES = [ 'application/json', 'application/pdf', 'text/csv' ]; -export const UI_SETTINGS_CUSTOM_PDF_LOGO = 'xpackReporting:customPdfLogo'; \ No newline at end of file +export const UI_SETTINGS_CUSTOM_PDF_LOGO = 'xpackReporting:customPdfLogo'; + +/** + * The type name used within the Monitoring index to publish reporting stats. + * @type {string} + */ +export const KIBANA_REPORTING_TYPE = 'reporting_stats'; diff --git a/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js b/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js index c5ff91ffd20da2..d42d6fffef6dd2 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js +++ b/x-pack/plugins/reporting/export_types/csv/server/__tests__/execute_job.js @@ -7,15 +7,15 @@ import expect from 'expect.js'; import Puid from 'puid'; import sinon from 'sinon'; -import 'sinon-as-promised'; import nodeCrypto from '@elastic/node-crypto'; -import { resolveKibanaPath } from '@kbn/plugin-helpers'; -import { executeJobFactory } from '../execute_job'; + import { CancellationToken } from '../../../../server/lib/esqueue/helpers/cancellation_token'; -const { SavedObjectsClient } = require(resolveKibanaPath('src/server/saved_objects/client/saved_objects_client.js')); -const { FieldFormat } = require(resolveKibanaPath('src/ui/field_formats/field_format.js')); -const { FieldFormatsService } = require(resolveKibanaPath('src/ui/field_formats/field_formats_service.js')); -const { createStringFormat } = require(resolveKibanaPath('src/core_plugins/kibana/common/field_formats/types/string.js')); +import { SavedObjectsClient } from '../../../../../../../src/server/saved_objects/client/saved_objects_client.js'; +import { FieldFormat } from '../../../../../../../src/ui/field_formats/field_format.js'; +import { FieldFormatsService } from '../../../../../../../src/ui/field_formats/field_formats_service.js'; +import { createStringFormat } from '../../../../../../../src/core_plugins/kibana/common/field_formats/types/string.js'; + +import { executeJobFactory } from '../execute_job'; const delay = (ms) => new Promise(resolve => setTimeout(() => resolve(), ms)); @@ -369,7 +369,7 @@ describe('CSV Execute Job', function () { // that delays the Promise resolution so we have a chance to call cancellationToken.cancel(). // Otherwise, we get into an endless loop, and don't have a chance to call cancel callWithRequestStub.restore(); - callWithRequestStub = sinon.stub(clusterStub, 'callWithRequest', async function () { + callWithRequestStub = sinon.stub(clusterStub, 'callWithRequest').callsFake(async function () { await delay(1); return { hits: { diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js index 2cac676fb6e2a3..696ae16d11e798 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js +++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js @@ -5,12 +5,13 @@ */ import expect from 'expect.js'; + +import { FieldFormat } from '../../../../../../../../src/ui/field_formats/field_format.js'; +import { FieldFormatsService } from '../../../../../../../../src/ui/field_formats/field_formats_service.js'; +import { createBytesFormat } from '../../../../../../../../src/core_plugins/kibana/common/field_formats/types/bytes.js'; +import { createNumberFormat } from '../../../../../../../../src/core_plugins/kibana/common/field_formats/types/number.js'; + import { fieldFormatMapFactory } from '../field_format_map'; -import { resolveKibanaPath } from '@kbn/plugin-helpers'; -const { FieldFormat } = require(resolveKibanaPath('src/ui/field_formats/field_format.js')); -const { FieldFormatsService } = require(resolveKibanaPath('src/ui/field_formats/field_formats_service.js')); -const { createBytesFormat } = require(resolveKibanaPath('src/core_plugins/kibana/common/field_formats/types/bytes.js')); -const { createNumberFormat } = require(resolveKibanaPath('src/core_plugins/kibana/common/field_formats/types/number.js')); describe('field format map', function () { const indexPatternSavedObject = { diff --git a/x-pack/plugins/reporting/index.js b/x-pack/plugins/reporting/index.js index 69b01ab68f9344..4e4b2d18e59cc1 100644 --- a/x-pack/plugins/reporting/index.js +++ b/x-pack/plugins/reporting/index.js @@ -18,7 +18,8 @@ import { exportTypesRegistryFactory } from './server/lib/export_types_registry'; import { createBrowserDriverFactory, getDefaultBrowser, getDefaultChromiumSandboxDisabled } from './server/browsers'; import { logConfiguration } from './log_configuration'; -export { getReportingUsage } from './server/usage'; +import { callClusterFactory } from '../xpack_main'; +import { getReportingUsageCollector } from './server/usage'; const kbToBase64Length = (kb) => { return Math.floor((kb * 1024 * 8) / 6); @@ -47,15 +48,17 @@ export const reporting = (kibana) => { }, uiSettingDefaults: { [UI_SETTINGS_CUSTOM_PDF_LOGO]: { - description: `Custom image to use in the PDF's footer`, + name: 'PDF footer image', value: null, + description: `Custom image to use in the PDF's footer`, type: 'image', options: { maxSize: { length: kbToBase64Length(200), description: '200 kB', } - } + }, + category: ['reporting'], } } }, @@ -144,7 +147,8 @@ export const reporting = (kibana) => { validateConfig(config, message => server.log(['reporting', 'warning'], message)); logConfiguration(config, message => server.log(['reporting', 'debug'], message)); - const xpackMainPlugin = server.plugins.xpack_main; + const { xpack_main: xpackMainPlugin, monitoring: monitoringPlugin } = server.plugins; + mirrorPluginStatus(xpackMainPlugin, this); const checkLicense = checkLicenseFactory(exportTypesRegistry); xpackMainPlugin.status.once('green', () => { @@ -153,6 +157,14 @@ export const reporting = (kibana) => { xpackMainPlugin.info.feature(this.id).registerLicenseCheckResultsGenerator(checkLicense); }); + // Register a function to with Monitoring to manage the collection of usage stats + monitoringPlugin.status.once('green', () => { + if (monitoringPlugin.collectorSet) { + const callCluster = callClusterFactory(server).getCallClusterInternal(); // uses callWithInternal as this is for internal collection + monitoringPlugin.collectorSet.register(getReportingUsageCollector(server, callCluster)); + } + }); + server.expose('browserDriverFactory', await createBrowserDriverFactory(server)); server.expose('queue', createQueueFactory(server)); diff --git a/x-pack/plugins/reporting/public/assets/app_reporting.svg b/x-pack/plugins/reporting/public/assets/app_reporting.svg deleted file mode 100644 index ec24791c5b09d3..00000000000000 --- a/x-pack/plugins/reporting/public/assets/app_reporting.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/x-pack/plugins/reporting/public/directives/export_config/export_config.js b/x-pack/plugins/reporting/public/directives/export_config/export_config.js index 580ab2d3c4a3a0..f88338832d389d 100644 --- a/x-pack/plugins/reporting/public/directives/export_config/export_config.js +++ b/x-pack/plugins/reporting/public/directives/export_config/export_config.js @@ -104,9 +104,13 @@ module.directive('exportConfig', ($rootScope, reportingDocumentControl, reportin }); } + const defaultMessage = err.status === 403 + ? `You don't have permission to generate this report.` + : `Can't reach the server. Please try again.`; + toastNotifications.addDanger({ title: 'Reporting error', - text: err.message || `Can't reach the server. Please try again.`, + text: err.message || defaultMessage, 'data-test-subj': 'queueReportError', }); }); diff --git a/x-pack/plugins/reporting/public/register_feature.js b/x-pack/plugins/reporting/public/register_feature.js index 84f8ead8053fba..0cb6220cdfbe6d 100644 --- a/x-pack/plugins/reporting/public/register_feature.js +++ b/x-pack/plugins/reporting/public/register_feature.js @@ -13,7 +13,7 @@ FeatureCatalogueRegistryProvider.register(() => { id: 'reporting', title: 'Reporting', description: 'Manage your reports generated from Discover, Visualize, and Dashboard.', - icon: '/plugins/reporting/assets/app_reporting.svg', + icon: 'reportingApp', path: '/app/kibana#/management/kibana/reporting', showOnHomePage: false, category: FeatureCatalogueCategory.ADMIN diff --git a/x-pack/plugins/reporting/public/services/job_completion_notifications.js b/x-pack/plugins/reporting/public/services/job_completion_notifications.js index 8e480b35e1a9ad..82506d54480829 100644 --- a/x-pack/plugins/reporting/public/services/job_completion_notifications.js +++ b/x-pack/plugins/reporting/public/services/job_completion_notifications.js @@ -7,18 +7,19 @@ import { uiModules } from 'ui/modules'; import { JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY } from '../../common/constants'; -class JobCompletionNotifications { - +export const jobCompletionNotifications = { add(jobId) { const jobs = this.getAll(); jobs.push(jobId); this._set(jobs); - } + }, getAll() { - const sessionValue = sessionStorage.getItem(JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY); + const sessionValue = sessionStorage.getItem( + JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY + ); return sessionValue ? JSON.parse(sessionValue) : []; - } + }, remove(jobId) { const jobs = this.getAll(); @@ -29,14 +30,16 @@ class JobCompletionNotifications { jobs.splice(index, 1); this._set(jobs); - } + }, _set(jobs) { - sessionStorage.setItem(JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY, JSON.stringify(jobs)); - } -} - -uiModules.get('xpack/reporting') - .factory('reportingJobCompletionNotifications', function () { - return new JobCompletionNotifications(); - }); + sessionStorage.setItem( + JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY, + JSON.stringify(jobs) + ); + }, +}; + +uiModules + .get('xpack/reporting') + .factory('reportingJobCompletionNotifications', () => jobCompletionNotifications); diff --git a/x-pack/plugins/reporting/server/lib/__tests__/authorized_user_pre_routing.js b/x-pack/plugins/reporting/server/lib/__tests__/authorized_user_pre_routing.js index 26b414cfac31c6..665de2068a4916 100644 --- a/x-pack/plugins/reporting/server/lib/__tests__/authorized_user_pre_routing.js +++ b/x-pack/plugins/reporting/server/lib/__tests__/authorized_user_pre_routing.js @@ -57,7 +57,7 @@ describe('authorized_user_pre_routing', function () { } }; - callWithRequestStub.reset(); + callWithRequestStub.resetHistory(); callWithRequestStub.returns(Promise.resolve(user)); return mockServer; }; diff --git a/x-pack/plugins/reporting/server/lib/__tests__/validate_config.js b/x-pack/plugins/reporting/server/lib/__tests__/validate_config.js index deca78f7ac57e6..ef460ff19574c4 100644 --- a/x-pack/plugins/reporting/server/lib/__tests__/validate_config.js +++ b/x-pack/plugins/reporting/server/lib/__tests__/validate_config.js @@ -12,7 +12,7 @@ describe('Reporting: Validate config', function () { const log = sinon.spy(); beforeEach(() => { - log.reset(); + log.resetHistory(); }); [undefined, null].forEach(value => { diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js index a89189cc95ba33..698f7e1605aa75 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/helpers/create_index.js @@ -102,7 +102,7 @@ describe('Create Index', function () { beforeEach(function () { client = new ClientMock(); - sinon.stub(client.indices, 'exists', () => Promise.resolve(true)); + sinon.stub(client.indices, 'exists').callsFake(() => Promise.resolve(true)); createSpy = sinon.spy(client.indices, 'create'); }); diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js index d4af1aa85744e5..d928f82f3abb36 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js @@ -38,7 +38,7 @@ describe('Job Class', function () { let options; beforeEach(function () { - createIndexMock.reset(); + createIndexMock.resetHistory(); createIndexMock.returns(Promise.resolve('mock')); index = 'test'; @@ -163,7 +163,7 @@ describe('Job Class', function () { const errMsg = 'test document index failure'; client.index.restore(); - sinon.stub(client, 'index', () => Promise.reject(new Error(errMsg))); + sinon.stub(client, 'index').callsFake(() => Promise.reject(new Error(errMsg))); const job = new Job(mockQueue, index, type, payload); job.once(constants.EVENT_JOB_CREATE_ERROR, (err) => { diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js index cc6f0cff7a594e..d480a1ad15429d 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js @@ -211,7 +211,7 @@ describe('Worker class', function () { it('should start polling for jobs after interval', async function () { worker = new Worker(mockQueue, 'test', noop, defaultWorkerOptions); - const processPendingJobsStub = sinon.stub(worker, '_processPendingJobs', () => Promise.resolve()); + const processPendingJobsStub = sinon.stub(worker, '_processPendingJobs').callsFake(() => Promise.resolve()); sinon.assert.notCalled(processPendingJobsStub); await allowPoll(defaultWorkerOptions.interval); sinon.assert.calledOnce(processPendingJobsStub); @@ -220,7 +220,7 @@ describe('Worker class', function () { it('should use interval option to control polling', async function () { const interval = 567; worker = new Worker(mockQueue, 'test', noop, { ...defaultWorkerOptions, interval }); - const processPendingJobsStub = sinon.stub(worker, '_processPendingJobs', () => Promise.resolve()); + const processPendingJobsStub = sinon.stub(worker, '_processPendingJobs').callsFake(() => Promise.resolve()); sinon.assert.notCalled(processPendingJobsStub); await allowPoll(interval); @@ -230,7 +230,7 @@ describe('Worker class', function () { it('should not poll once destroyed', async function () { worker = new Worker(mockQueue, 'test', noop, defaultWorkerOptions); - const processPendingJobsStub = sinon.stub(worker, '_processPendingJobs', () => Promise.resolve()); + const processPendingJobsStub = sinon.stub(worker, '_processPendingJobs').callsFake(() => Promise.resolve()); // move the clock a couple times, test for searches each time sinon.assert.notCalled(processPendingJobsStub); @@ -266,7 +266,7 @@ describe('Worker class', function () { it('should not use error multiplier when processPendingJobs resolved the Promise', async function () { worker = new Worker(mockQueue, 'test', noop, defaultWorkerOptions); - const processPendingJobsStub = sinon.stub(worker, "_processPendingJobs", () => Promise.resolve()); + const processPendingJobsStub = sinon.stub(worker, "_processPendingJobs").callsFake(() => Promise.resolve()); await allowPoll(defaultWorkerOptions.interval); expect(processPendingJobsStub.callCount).to.be(1); @@ -289,7 +289,7 @@ describe('Worker class', function () { }); it('should pass search errors', function (done) { - searchStub = sinon.stub(mockQueue.client, 'search', () => Promise.reject()); + searchStub = sinon.stub(mockQueue.client, 'search').callsFake(() => Promise.reject()); worker = new Worker(mockQueue, 'test', noop, defaultWorkerOptions); worker._getPendingJobs() .then(() => done(new Error('should not resolve'))) @@ -301,7 +301,7 @@ describe('Worker class', function () { describe('missing index', function () { it('should swallow error', function (done) { - searchStub = sinon.stub(mockQueue.client, 'search', () => Promise.reject({ + searchStub = sinon.stub(mockQueue.client, 'search').callsFake(() => Promise.reject({ status: 404 })); worker = new Worker(mockQueue, 'test', noop, defaultWorkerOptions); @@ -311,7 +311,7 @@ describe('Worker class', function () { }); it('should return an empty array', function (done) { - searchStub = sinon.stub(mockQueue.client, 'search', () => Promise.reject({ + searchStub = sinon.stub(mockQueue.client, 'search').callsFake(() => Promise.reject({ status: 404 })); worker = new Worker(mockQueue, 'test', noop, defaultWorkerOptions); @@ -333,7 +333,7 @@ describe('Worker class', function () { describe('query parameters', function () { beforeEach(() => { - searchStub = sinon.stub(mockQueue.client, 'search', () => Promise.resolve({ hits: { hits: [] } })); + searchStub = sinon.stub(mockQueue.client, 'search').callsFake(() => Promise.resolve({ hits: { hits: [] } })); }); it('should query with version', function () { @@ -358,7 +358,7 @@ describe('Worker class', function () { const jobtype = 'test_jobtype'; beforeEach(() => { - searchStub = sinon.stub(mockQueue.client, 'search', () => Promise.resolve({ hits: { hits: [] } })); + searchStub = sinon.stub(mockQueue.client, 'search').callsFake(() => Promise.resolve({ hits: { hits: [] } })); anchorMoment = moment(anchor); clock = sinon.useFakeTimers(anchorMoment.valueOf()); }); @@ -907,7 +907,7 @@ describe('Worker class', function () { }; beforeEach(function () { - sinon.stub(mockQueue.client, 'search', () => Promise.resolve({ hits: { hits: [] } })); + sinon.stub(mockQueue.client, 'search').callsFake(() => Promise.resolve({ hits: { hits: [] } })); }); describe('workerFn rejects promise', function () { diff --git a/x-pack/plugins/reporting/server/usage/get_usage.js b/x-pack/plugins/reporting/server/usage/get_reporting_usage_collector.js similarity index 70% rename from x-pack/plugins/reporting/server/usage/get_usage.js rename to x-pack/plugins/reporting/server/usage/get_reporting_usage_collector.js index 8bb90eedffa459..6c129a45108cbb 100644 --- a/x-pack/plugins/reporting/server/usage/get_usage.js +++ b/x-pack/plugins/reporting/server/usage/get_reporting_usage_collector.js @@ -6,9 +6,9 @@ import { uniq } from 'lodash'; import { getExportTypesHandler } from './get_export_type_handler'; -import { - getReportCountsByParameter, -} from './get_reporting_type_counts'; +import { getReportCountsByParameter } from './get_reporting_type_counts'; +import { KIBANA_REPORTING_TYPE } from '../../common/constants'; +import { UsageCollector } from '../../../monitoring/server/kibana_monitoring'; /** * @typedef {Object} ReportingUsageStats Almost all of these stats are optional. @@ -110,34 +110,44 @@ async function getReportingUsageWithinRange(callCluster, server, reportingAvaila }; } -export async function getReportingUsage(callCluster, server) { - const xpackInfo = server.plugins.xpack_main.info; - const config = server.config(); - const available = xpackInfo && xpackInfo.isAvailable(); // some form of reporting (csv at least) is available for all valid licenses - const enabled = config.get('xpack.reporting.enabled'); // follow ES behavior: if its not available then its not enabled - const reportingAvailable = available && enabled; - - const statsOverAllTime = await getReportingUsageWithinRange(callCluster, server, reportingAvailable); - const statsOverLast1Day = await getReportingUsageWithinRange(callCluster, server, reportingAvailable, 1); - const statsOverLast7Days = await getReportingUsageWithinRange(callCluster, server, reportingAvailable, 7); - - let browserType; - if (enabled) { - // Allow this to explictly throw an exception if/when this config is deprecated, - // because we shouldn't collect browserType in that case! - browserType = config.get('xpack.reporting.capture.browser.type'); - } +/* + * @param {Object} server + * @param {Function} callCluster - function that uses either callWithRequest or callWithInternal to fetch data from ES + * @return {Object} kibana usage stats type collection object + */ +export function getReportingUsageCollector(server, callCluster) { + return new UsageCollector(server, { + type: KIBANA_REPORTING_TYPE, + fetch: async () => { + const xpackInfo = server.plugins.xpack_main.info; + const config = server.config(); + const available = xpackInfo && xpackInfo.isAvailable(); // some form of reporting (csv at least) is available for all valid licenses + const enabled = config.get('xpack.reporting.enabled'); // follow ES behavior: if its not available then its not enabled + const reportingAvailable = available && enabled; + + const statsOverAllTime = await getReportingUsageWithinRange(callCluster, server, reportingAvailable); + const statsOverLast1Day = await getReportingUsageWithinRange(callCluster, server, reportingAvailable, 1); + const statsOverLast7Days = await getReportingUsageWithinRange(callCluster, server, reportingAvailable, 7); + + let browserType; + if (enabled) { + // Allow this to explictly throw an exception if/when this config is deprecated, + // because we shouldn't collect browserType in that case! + browserType = config.get('xpack.reporting.capture.browser.type'); + } - return { - available, - enabled: available && enabled, // similar behavior as _xpack API in ES - browser_type: browserType, - ...statsOverAllTime, - lastDay: { - ...statsOverLast1Day - }, - last7Days: { - ...statsOverLast7Days + return { + available, + enabled: available && enabled, // similar behavior as _xpack API in ES + browser_type: browserType, + ...statsOverAllTime, + lastDay: { + ...statsOverLast1Day + }, + last7Days: { + ...statsOverLast7Days + } + }; } - }; + }); } diff --git a/x-pack/plugins/reporting/server/usage/get_usage.test.js b/x-pack/plugins/reporting/server/usage/get_reporting_usage_collector.test.js similarity index 83% rename from x-pack/plugins/reporting/server/usage/get_usage.test.js rename to x-pack/plugins/reporting/server/usage/get_reporting_usage_collector.test.js index ab3c773bd79c59..c92643dbcfd363 100644 --- a/x-pack/plugins/reporting/server/usage/get_usage.test.js +++ b/x-pack/plugins/reporting/server/usage/get_reporting_usage_collector.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import sinon from 'sinon'; -import { getReportingUsage } from './get_usage'; +import { getReportingUsageCollector } from './get_reporting_usage_collector'; function getServerMock(customization) { const getLicenseCheckResults = sinon.stub().returns({}); @@ -52,7 +52,8 @@ test('sets enabled to false when reporting is turned off', async () => { }); const serverMock = getServerMock({ config: () => ({ get: mockConfigGet }) }); const callClusterMock = jest.fn(); - const usageStats = await getReportingUsage(callClusterMock, serverMock); + const { fetch: getReportingUsage } = getReportingUsageCollector(serverMock, callClusterMock); + const usageStats = await getReportingUsage(); expect(usageStats.enabled).toBe(false); }); @@ -62,7 +63,8 @@ describe('with a basic license', async () => { const serverWithBasicLicenseMock = getServerMock(); serverWithBasicLicenseMock.plugins.xpack_main.info.license.getType = sinon.stub().returns('basic'); const callClusterMock = jest.fn(() => Promise.resolve({})); - usageStats = await getReportingUsage(callClusterMock, serverWithBasicLicenseMock); + const { fetch: getReportingUsage } = getReportingUsageCollector(serverWithBasicLicenseMock, callClusterMock); + usageStats = await getReportingUsage(); }); test('sets enables to true', async () => { @@ -84,7 +86,8 @@ describe('with no license', async () => { const serverWithNoLicenseMock = getServerMock(); serverWithNoLicenseMock.plugins.xpack_main.info.license.getType = sinon.stub().returns('none'); const callClusterMock = jest.fn(() => Promise.resolve({})); - usageStats = await getReportingUsage(callClusterMock, serverWithNoLicenseMock); + const { fetch: getReportingUsage } = getReportingUsageCollector(serverWithNoLicenseMock, callClusterMock); + usageStats = await getReportingUsage(); }); test('sets enables to true', async () => { @@ -106,7 +109,8 @@ describe('with platinum license', async () => { const serverWithPlatinumLicenseMock = getServerMock(); serverWithPlatinumLicenseMock.plugins.xpack_main.info.license.getType = sinon.stub().returns('platinum'); const callClusterMock = jest.fn(() => Promise.resolve({})); - usageStats = await getReportingUsage(callClusterMock, serverWithPlatinumLicenseMock); + const { fetch: getReportingUsage } = getReportingUsageCollector(serverWithPlatinumLicenseMock, callClusterMock); + usageStats = await getReportingUsage(); }); test('sets enables to true', async () => { diff --git a/x-pack/plugins/reporting/server/usage/index.js b/x-pack/plugins/reporting/server/usage/index.js index 37988d9b21c700..91e2a9284550b1 100644 --- a/x-pack/plugins/reporting/server/usage/index.js +++ b/x-pack/plugins/reporting/server/usage/index.js @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { getReportingUsage } from './get_usage'; +export { getReportingUsageCollector } from './get_reporting_usage_collector'; diff --git a/x-pack/plugins/searchprofiler/public/assets/app_search_profiler.svg b/x-pack/plugins/searchprofiler/public/assets/app_search_profiler.svg deleted file mode 100644 index 0f18da5c59da34..00000000000000 --- a/x-pack/plugins/searchprofiler/public/assets/app_search_profiler.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/x-pack/plugins/searchprofiler/public/register_feature.js b/x-pack/plugins/searchprofiler/public/register_feature.js index 5db3cdfcba7fc1..17070fe68be260 100644 --- a/x-pack/plugins/searchprofiler/public/register_feature.js +++ b/x-pack/plugins/searchprofiler/public/register_feature.js @@ -13,7 +13,7 @@ FeatureCatalogueRegistryProvider.register(() => { id: 'searchprofiler', title: 'Search Profiler', description: 'Quickly check the performance of any Elasticsearch query.', - icon: '/plugins/searchprofiler/assets/app_search_profiler.svg', + icon: 'searchProfilerApp', path: '/app/kibana#/dev_tools/searchprofiler', showOnHomePage: false, category: FeatureCatalogueCategory.ADMIN diff --git a/x-pack/plugins/security/public/register_feature.js b/x-pack/plugins/security/public/register_feature.js index 43b43ab1e90b29..3a14bad5e2d9de 100644 --- a/x-pack/plugins/security/public/register_feature.js +++ b/x-pack/plugins/security/public/register_feature.js @@ -13,7 +13,7 @@ FeatureCatalogueRegistryProvider.register(() => { id: 'security', title: 'Security Settings', description: 'Protect your data and easily manage who has access to what with users and roles.', - icon: '/plugins/kibana/assets/app_security.svg', + icon: 'securityApp', path: '/app/kibana#/management/security', showOnHomePage: true, category: FeatureCatalogueCategory.ADMIN diff --git a/x-pack/plugins/security/public/views/management/change_password_form/change_password_form.html b/x-pack/plugins/security/public/views/management/change_password_form/change_password_form.html index 1cd8289e85e58d..86fe29ece0c26f 100644 --- a/x-pack/plugins/security/public/views/management/change_password_form/change_password_form.html +++ b/x-pack/plugins/security/public/views/management/change_password_form/change_password_form.html @@ -11,7 +11,7 @@ ng-show="!changePasswordController.isFormVisible" ng-click="changePasswordController.showForm()" > - Change Password + Change password @@ -22,7 +22,7 @@
- Password must be at least 6 characters long. + Password must be at least 6 characters
- Passwords do not match. + Passwords do not match
@@ -93,7 +93,7 @@ ng-show="showKibanaWarning" > - After changing the password for the kibana user, you will need to update kibana.yml and restart Kibana. + After you change the password for the kibana user, you must update the kibana.yml file and restart Kibana
@@ -105,7 +105,7 @@ ng-click="onChangePassword({ newPassword: changePasswordController.newPassword, currentPassword: changePasswordController.currentPassword, onSuccess: changePasswordController.hideForm, onIncorrectPassword: changePasswordController.onIncorrectPassword })" ng-disabled="changePasswordForm.newPassword.$invalid || (changePasswordController.newPassword !== changePasswordController.newPasswordConfirmation)" > - Save + Save changes
@@ -83,7 +83,7 @@

class="kuiInputNote kuiInputNote--danger" ng-show="form.fullname.$touched && form.fullname.$error.required" > - Full Name is required. + Full name is required

@@ -126,7 +126,7 @@

class="kuiInputNote kuiInputNote--danger" ng-show="form.email.$touched && form.email.$error.required" > - Email is required. + Email is required

@@ -141,7 +141,7 @@

ng-disabled="user.metadata._reserved" data-test-subj="userFormRolesDropdown" > - + {{$item}} @@ -160,7 +160,7 @@

ng-click="saveUser(user)" data-test-subj="userFormSaveButton" > - Save + Add user - Password must be at least 6 characters long. + Password must be at least 6 characters

- Passwords do not match. + Passwords do not match
diff --git a/x-pack/plugins/security/public/views/management/users.html b/x-pack/plugins/security/public/views/management/users.html index 39bd91acee6556..3ab259faf9c02d 100644 --- a/x-pack/plugins/security/public/views/management/users.html +++ b/x-pack/plugins/security/public/views/management/users.html @@ -26,7 +26,7 @@ @@ -56,7 +56,7 @@ > - Create user + Add user
@@ -69,7 +69,7 @@
- No matching users found. + No users match your search criteria
@@ -100,7 +100,7 @@ aria-label="{{sort.reverse ? 'Sort full name ascending' : 'Sort full name descending'}}" > - Full Name + Full name diff --git a/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js b/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js index 1886fa9f6e0cc8..61955452c03d7d 100644 --- a/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js +++ b/x-pack/plugins/security/server/lib/__tests__/auth_redirect.js @@ -111,7 +111,14 @@ describe('lib/auth_redirect', function () { await authenticate(request, reply); - sinon.assert.calledWithExactly(reply, Boom.unauthorized()); + sinon.assert.calledWithExactly( + reply, + sinon.match({ + isBoom: true, + message: 'Unauthorized', + output: { statusCode: 401 }, + }) + ); sinon.assert.notCalled(reply.redirect); sinon.assert.notCalled(reply.continue); }); diff --git a/x-pack/plugins/security/server/lib/__tests__/validate_config.js b/x-pack/plugins/security/server/lib/__tests__/validate_config.js index 2804f50f4c9769..e8ba58cf23aec3 100644 --- a/x-pack/plugins/security/server/lib/__tests__/validate_config.js +++ b/x-pack/plugins/security/server/lib/__tests__/validate_config.js @@ -10,7 +10,7 @@ import { validateConfig } from '../validate_config'; describe('Validate config', function () { let config; - const log = sinon.spy(); + const log = sinon.stub(); const validKey = 'd624dce49dafa1401be7f3e1182b756a'; beforeEach(() => { @@ -19,7 +19,7 @@ describe('Validate config', function () { getDefault: sinon.stub(), set: sinon.stub(), }; - log.reset(); + log.resetHistory(); }); it('should log a warning and set xpack.security.encryptionKey if not set', function () { diff --git a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js index dbf3ad77875d60..ab32f30c2e3156 100644 --- a/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js +++ b/x-pack/plugins/security/server/lib/authentication/__tests__/authenticator.js @@ -16,7 +16,7 @@ import { initAuthenticator } from '../authenticator'; import * as ClientShield from '../../../../../../server/lib/get_client_shield'; describe('Authenticator', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); let config; let server; diff --git a/x-pack/plugins/security/server/lib/authentication/__tests__/session.js b/x-pack/plugins/security/server/lib/authentication/__tests__/session.js index b22a678fdd3950..1c8612ad2f4d76 100644 --- a/x-pack/plugins/security/server/lib/authentication/__tests__/session.js +++ b/x-pack/plugins/security/server/lib/authentication/__tests__/session.js @@ -11,7 +11,7 @@ import { serverFixture } from '../../__tests__/__fixtures__/server'; import { Session } from '../session'; describe('Session', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); let server; let config; @@ -110,14 +110,14 @@ describe('Session', () => { sinon.assert.calledOnce(callback); sinon.assert.calledWithExactly(callback, null, true, sessionWithoutExpires); - callback.reset(); + callback.resetHistory(); const notExpiredSession = { token: 'token', expires: currentTime + 1 }; validateFunc({}, notExpiredSession, callback); sinon.assert.calledOnce(callback); sinon.assert.calledWithExactly(callback, null, true, notExpiredSession); - callback.reset(); + callback.resetHistory(); const expiredSession = { token: 'token', expires: currentTime - 1 }; validateFunc({}, expiredSession, callback); diff --git a/x-pack/plugins/security/server/lib/authorization/__snapshots__/create_default_roles.test.js.snap b/x-pack/plugins/security/server/lib/authorization/__snapshots__/create_default_roles.test.js.snap new file mode 100644 index 00000000000000..9fdbc5479a0225 --- /dev/null +++ b/x-pack/plugins/security/server/lib/authorization/__snapshots__/create_default_roles.test.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`dashboard_only_user throws error when shield.getRole throws non 404 error 1`] = `undefined`; + +exports[`dashboard_only_user throws error when shield.putRole throws error 1`] = `"Some other error"`; + +exports[`rbac_user throws error when sheild.getRole throws non 404 error 1`] = `undefined`; + +exports[`rbac_user throws error when shield.putRole throws error 1`] = `"Some other error"`; diff --git a/x-pack/plugins/security/server/lib/authorization/create_default_roles.test.js b/x-pack/plugins/security/server/lib/authorization/create_default_roles.test.js new file mode 100644 index 00000000000000..98d95cd6e9fbf5 --- /dev/null +++ b/x-pack/plugins/security/server/lib/authorization/create_default_roles.test.js @@ -0,0 +1,216 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createDefaultRoles } from './create_default_roles'; +import { getClient } from '../../../../../server/lib/get_client_shield'; +import { DEFAULT_RESOURCE } from '../../../common/constants'; + +jest.mock('../../../../../server/lib/get_client_shield', () => ({ + getClient: jest.fn() +})); + +const mockShieldClient = () => { + const mockCallWithInternalUser = jest.fn(); + getClient.mockReturnValue({ + callWithInternalUser: mockCallWithInternalUser + }); + + return { + mockCallWithInternalUser + }; +}; + +const defaultApplication = 'foo-application'; + +const createMockServer = ({ settings = {} } = {}) => { + const mockServer = { + config: jest.fn().mockReturnValue({ + get: jest.fn() + }) + }; + + const defaultSettings = { + 'xpack.security.rbac.createDefaultRoles': true, + 'xpack.security.rbac.application': defaultApplication + }; + + mockServer.config().get.mockImplementation(key => { + return key in settings ? settings[key] : defaultSettings[key]; + }); + + return mockServer; +}; + +test(`doesn't create roles if createDefaultRoles is false`, async () => { + const { mockCallWithInternalUser } = mockShieldClient(); + const mockServer = createMockServer({ + settings: { + 'xpack.security.rbac.createDefaultRoles': false + } + }); + + await createDefaultRoles(mockServer); + + expect(mockCallWithInternalUser).toHaveBeenCalledTimes(0); +}); + +describe(`rbac_user`, () => { + test(`doesn't create \${application}_rbac_user when it exists`, async () => { + const { mockCallWithInternalUser } = mockShieldClient(); + const mockServer = createMockServer(); + mockCallWithInternalUser.mockReturnValue(null); + + await createDefaultRoles(mockServer); + + expect(mockCallWithInternalUser).not.toHaveBeenCalledWith('shield.putRole', expect.anything()); + }); + + test(`creates \${application}_rbac_user when it doesn't exist`, async () => { + const { mockCallWithInternalUser } = mockShieldClient(); + const mockServer = createMockServer(); + mockCallWithInternalUser.mockImplementation(async (endpoint, params) => { + if (endpoint === 'shield.getRole' && params.name === `${defaultApplication}_rbac_user`) { + throw { + statusCode: 404 + }; + } + + return null; + }); + + await createDefaultRoles(mockServer); + + expect(mockCallWithInternalUser).toHaveBeenCalledWith('shield.putRole', { + name: `${defaultApplication}_rbac_user`, + body: { + cluster: [], + index: [], + applications: [ + { + application: defaultApplication, + privileges: [ 'all' ], + resources: [ DEFAULT_RESOURCE ] + } + ] + } + }); + }); + + test(`throws error when sheild.getRole throws non 404 error`, async () => { + const { mockCallWithInternalUser } = mockShieldClient(); + const mockServer = createMockServer(); + mockCallWithInternalUser.mockImplementation(async (endpoint, params) => { + if (endpoint === 'shield.getRole' && params.name === `${defaultApplication}_rbac_user`) { + throw { + statusCode: 500 + }; + } + + return null; + }); + + expect(createDefaultRoles(mockServer)).rejects.toThrowErrorMatchingSnapshot(); + }); + + test(`throws error when shield.putRole throws error`, async () => { + const { mockCallWithInternalUser } = mockShieldClient(); + const mockServer = createMockServer(); + mockCallWithInternalUser.mockImplementation(async (endpoint, params) => { + if (endpoint === 'shield.getRole' && params.name === `${defaultApplication}_rbac_user`) { + throw { + statusCode: 404 + }; + } + + if (endpoint === 'shield.putRole' && params.name === `${defaultApplication}_rbac_user`) { + throw new Error('Some other error'); + } + + return null; + }); + + await expect(createDefaultRoles(mockServer)).rejects.toThrowErrorMatchingSnapshot(); + }); +}); + +describe(`dashboard_only_user`, () => { + test(`doesn't create \${application}_rbac_dashboard_only_user when it exists`, async () => { + const { mockCallWithInternalUser } = mockShieldClient(); + const mockServer = createMockServer(); + mockCallWithInternalUser.mockReturnValue(null); + + await createDefaultRoles(mockServer); + + expect(mockCallWithInternalUser).not.toHaveBeenCalledWith('shield.putRole', expect.anything()); + }); + + test(`creates \${application}_rbac_dashboard_only_user when it doesn't exist`, async () => { + const { mockCallWithInternalUser } = mockShieldClient(); + const mockServer = createMockServer(); + mockCallWithInternalUser.mockImplementation(async (endpoint, params) => { + if (endpoint === 'shield.getRole' && params.name === `${defaultApplication}_rbac_dashboard_only_user`) { + throw { + statusCode: 404 + }; + } + + return null; + }); + + await createDefaultRoles(mockServer); + + expect(mockCallWithInternalUser).toHaveBeenCalledWith('shield.putRole', { + name: `${defaultApplication}_rbac_dashboard_only_user`, + body: { + cluster: [], + index: [], + applications: [ + { + application: defaultApplication, + privileges: [ 'read' ], + resources: [ DEFAULT_RESOURCE ] + } + ] + } + }); + }); + + test(`throws error when shield.getRole throws non 404 error`, async () => { + const { mockCallWithInternalUser } = mockShieldClient(); + const mockServer = createMockServer(); + mockCallWithInternalUser.mockImplementation(async (endpoint, params) => { + if (endpoint === 'shield.getRole' && params.name === `${defaultApplication}_rbac_dashboard_only_user`) { + throw { + statusCode: 500 + }; + } + + return null; + }); + + await expect(createDefaultRoles(mockServer)).rejects.toThrowErrorMatchingSnapshot(); + }); + + test(`throws error when shield.putRole throws error`, async () => { + const { mockCallWithInternalUser } = mockShieldClient(); + const mockServer = createMockServer(); + mockCallWithInternalUser.mockImplementation(async (endpoint, params) => { + if (endpoint === 'shield.getRole' && params.name === `${defaultApplication}_rbac_dashboard_only_user`) { + throw { + statusCode: 404 + }; + } + + if (endpoint === 'shield.putRole' && params.name === `${defaultApplication}_rbac_dashboard_only_user`) { + throw new Error('Some other error'); + } + + return null; + }); + + await expect(createDefaultRoles(mockServer)).rejects.toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js b/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js index d263d43d5114cc..0e4bcbf2f6a066 100644 --- a/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js +++ b/x-pack/plugins/security/server/routes/api/v1/__tests__/authenticate.js @@ -93,7 +93,15 @@ describe('Authentication routes', () => { sinon.assert.notCalled(replyStub.continue); sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, Boom.unauthorized(failureReason)); + + sinon.assert.calledWithExactly( + replyStub, + sinon.match({ + isBoom: true, + message: failureReason.toString(), + output: { statusCode: 401 }, + }) + ); }); it('returns 401 if authentication is not handled.', async () => { @@ -105,7 +113,15 @@ describe('Authentication routes', () => { sinon.assert.notCalled(replyStub.continue); sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, Boom.unauthorized()); + + sinon.assert.calledWithExactly( + replyStub, + sinon.match({ + isBoom: true, + message: 'Unauthorized', + output: { statusCode: 401 }, + }) + ); }); it('returns user data if authentication succeed.', async () => { @@ -183,7 +199,11 @@ describe('Authentication routes', () => { sinon.assert.calledOnce(replyStub); sinon.assert.calledWithExactly( replyStub, - Boom.badRequest('Client should be able to process redirect response.') + sinon.match({ + isBoom: true, + message: 'Client should be able to process redirect response.', + output: { statusCode: 400 } + }) ); sinon.assert.notCalled(replyStub.continue); sinon.assert.notCalled(replyStub.redirect); @@ -323,7 +343,14 @@ describe('Authentication routes', () => { sinon.assert.notCalled(replyStub.continue); sinon.assert.notCalled(replyStub.redirect); sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, Boom.unauthorized(failureReason)); + sinon.assert.calledWithExactly( + replyStub, + sinon.match({ + isBoom: true, + message: failureReason.toString(), + output: { statusCode: 401 } + }) + ); }); it('returns 401 if authentication is not handled.', async () => { @@ -336,7 +363,14 @@ describe('Authentication routes', () => { sinon.assert.notCalled(replyStub.continue); sinon.assert.notCalled(replyStub.redirect); sinon.assert.calledOnce(replyStub); - sinon.assert.calledWithExactly(replyStub, Boom.unauthorized()); + sinon.assert.calledWithExactly( + replyStub, + sinon.match({ + isBoom: true, + message: 'Unauthorized', + output: { statusCode: 401 } + }) + ); }); it('returns 403 if there an active session exists.', async () => { @@ -351,10 +385,12 @@ describe('Authentication routes', () => { sinon.assert.calledOnce(replyStub); sinon.assert.calledWithExactly( replyStub, - Boom.forbidden( - 'Sorry, you already have an active Kibana session. ' + - 'If you want to start a new one, please logout from the existing session first.' - ) + sinon.match({ + isBoom: true, + message: 'Sorry, you already have an active Kibana session. ' + + 'If you want to start a new one, please logout from the existing session first.', + output: { statusCode: 403 } + }) ); }); diff --git a/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js b/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js index 3473021d182d74..204b703bf0f15b 100644 --- a/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js +++ b/x-pack/plugins/security/server/routes/api/v1/__tests__/users.js @@ -15,7 +15,7 @@ import { initUsersApi } from '../users'; import * as ClientShield from '../../../../../../../server/lib/get_client_shield'; describe('User routes', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); let clusterStub; let serverStub; diff --git a/x-pack/plugins/watcher/public/assets/app_watches.svg b/x-pack/plugins/watcher/public/assets/app_watches.svg deleted file mode 100644 index 15252bf2660e95..00000000000000 --- a/x-pack/plugins/watcher/public/assets/app_watches.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/x-pack/plugins/watcher/public/register_feature.js b/x-pack/plugins/watcher/public/register_feature.js index bc7762024ea40a..a53a4196b8e884 100644 --- a/x-pack/plugins/watcher/public/register_feature.js +++ b/x-pack/plugins/watcher/public/register_feature.js @@ -13,7 +13,7 @@ FeatureCatalogueRegistryProvider.register(() => { id: 'watcher', title: 'Watcher', description: 'Detect changes in your data by creating, managing, and monitoring alerts.', - icon: '/plugins/watcher/assets/app_watches.svg', + icon: 'watchesApp', path: '/app/kibana#/management/elasticsearch/watcher/watches', showOnHomePage: true, category: FeatureCatalogueCategory.ADMIN diff --git a/x-pack/plugins/watcher/server/models/action/slack_action.js b/x-pack/plugins/watcher/server/models/action/slack_action.js index 9b2589f391ed2c..3f07023a4a2edc 100644 --- a/x-pack/plugins/watcher/server/models/action/slack_action.js +++ b/x-pack/plugins/watcher/server/models/action/slack_action.js @@ -69,9 +69,6 @@ export class SlackAction extends BaseAction { if (!json.actionJson.slack.message.to) { throw badRequest('json argument must contain an actionJson.slack.message.to property'); } - if (!json.actionJson.slack.message.text) { - throw badRequest('json argument must contain an actionJson.slack.message.text property'); - } Object.assign(props, { to: json.actionJson.slack.message.to, diff --git a/x-pack/plugins/watcher/server/models/settings/__tests__/settings.js b/x-pack/plugins/watcher/server/models/settings/__tests__/settings.js index 888b79aac8db31..6c34467ef8629b 100644 --- a/x-pack/plugins/watcher/server/models/settings/__tests__/settings.js +++ b/x-pack/plugins/watcher/server/models/settings/__tests__/settings.js @@ -29,6 +29,19 @@ describe('settings module', () => { describe('when upstream JSON contains a configured action type', () => { it('returns the correct Settings instance', () => { const upstreamJson = { + persistent: { + xpack: { + notification: { + email: { + account: { + foo: {}, + bar: {} + }, + default_account: 'bar' + } + } + } + }, defaults: { xpack: { notification: { @@ -49,6 +62,8 @@ describe('settings module', () => { expect(actionTypes.email.enabled).to.be(true); expect(actionTypes.email.accounts.scooby.default).to.be(true); expect(actionTypes.email.accounts.scrappy).to.be.an('object'); + expect(actionTypes.email.accounts.foo).to.be.an('object'); + expect(actionTypes.email.accounts.bar).to.be.an('object'); }); }); }); diff --git a/x-pack/plugins/watcher/server/models/settings/settings.js b/x-pack/plugins/watcher/server/models/settings/settings.js index dd81897a5eaee6..91970573f795fb 100644 --- a/x-pack/plugins/watcher/server/models/settings/settings.js +++ b/x-pack/plugins/watcher/server/models/settings/settings.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { get } from 'lodash'; +import { merge } from 'lodash'; import { ACTION_TYPES } from '../../../common/constants'; function isEnabledByDefault(actionType) { @@ -47,9 +47,21 @@ function getAccounts({ account, default_account: defaultAccount }) { }, {}); } +function getNotifications(json) { + if (!json) { + return {}; + } + return Object.values(json).reduce((accum, value) => { + if (value.hasOwnProperty('xpack') && value.xpack.hasOwnProperty('notification')) { + accum = merge(accum, value.xpack.notification); + } + return accum; + }, {}); +} + function getActionTypesSettings(upstreamJson) { - const upstreamActionTypes = get(upstreamJson, 'defaults.xpack.notification', {}); + const upstreamActionTypes = getNotifications(upstreamJson); // Initialize settings for known action types const actionTypes = Object.keys(ACTION_TYPES).reduce((types, typeName) => { diff --git a/x-pack/plugins/watcher/server/models/watch/__tests__/base_watch.js b/x-pack/plugins/watcher/server/models/watch/__tests__/base_watch.js index 8cbe7cc98d31a1..1316559561f375 100644 --- a/x-pack/plugins/watcher/server/models/watch/__tests__/base_watch.js +++ b/x-pack/plugins/watcher/server/models/watch/__tests__/base_watch.js @@ -262,7 +262,7 @@ describe('BaseWatch', () => { let downstreamJson; beforeEach(() => { - actionFromDownstreamJSONMock.reset(); + actionFromDownstreamJSONMock.resetHistory(); downstreamJson = { id: 'my-watch', @@ -316,8 +316,8 @@ describe('BaseWatch', () => { let upstreamJson; beforeEach(() => { - actionFromUpstreamJSONMock.reset(); - watchStatusFromUpstreamJSONMock.reset(); + actionFromUpstreamJSONMock.resetHistory(); + watchStatusFromUpstreamJSONMock.resetHistory(); upstreamJson = { id: 'my-watch', diff --git a/x-pack/plugins/watcher/server/models/watch/__tests__/json_watch.js b/x-pack/plugins/watcher/server/models/watch/__tests__/json_watch.js index 8608b5e5a923c7..e4b258d51cfe56 100644 --- a/x-pack/plugins/watcher/server/models/watch/__tests__/json_watch.js +++ b/x-pack/plugins/watcher/server/models/watch/__tests__/json_watch.js @@ -56,7 +56,7 @@ describe('JsonWatch', () => { let props; beforeEach(() => { - constructorMock.reset(); + constructorMock.resetHistory(); props = { watch: 'foo' @@ -99,7 +99,7 @@ describe('JsonWatch', () => { describe('upstreamJson getter method', () => { beforeEach(() => { - upstreamJsonMock.reset(); + upstreamJsonMock.resetHistory(); }); it('should call the getter from WatchBase and return the correct result', () => { @@ -119,7 +119,7 @@ describe('JsonWatch', () => { let props; beforeEach(() => { - downstreamJsonMock.reset(); + downstreamJsonMock.resetHistory(); props = { watch: 'foo', @@ -145,7 +145,7 @@ describe('JsonWatch', () => { let upstreamJson; beforeEach(() => { - getPropsFromUpstreamJsonMock.reset(); + getPropsFromUpstreamJsonMock.resetHistory(); upstreamJson = { watchJson: { foo: { bar: 'baz' } } @@ -199,7 +199,7 @@ describe('JsonWatch', () => { let downstreamJson; beforeEach(() => { - getPropsFromDownstreamJsonMock.reset(); + getPropsFromDownstreamJsonMock.resetHistory(); downstreamJson = { watch: { foo: { bar: 'baz' } } diff --git a/x-pack/plugins/watcher/server/models/watch/__tests__/monitoring_watch.js b/x-pack/plugins/watcher/server/models/watch/__tests__/monitoring_watch.js index 8b4c2e0d0455f1..c580d8c8f77688 100644 --- a/x-pack/plugins/watcher/server/models/watch/__tests__/monitoring_watch.js +++ b/x-pack/plugins/watcher/server/models/watch/__tests__/monitoring_watch.js @@ -41,7 +41,7 @@ describe('MonitoringWatch', () => { let props; beforeEach(() => { - constructorMock.reset(); + constructorMock.resetHistory(); props = {}; }); @@ -108,7 +108,7 @@ describe('MonitoringWatch', () => { let props; beforeEach(() => { - downstreamJsonMock.reset(); + downstreamJsonMock.resetHistory(); props = {}; }); @@ -129,7 +129,7 @@ describe('MonitoringWatch', () => { describe('fromUpstreamJson factory method', () => { beforeEach(() => { - getPropsFromUpstreamJsonMock.reset(); + getPropsFromUpstreamJsonMock.resetHistory(); }); it('should call the getPropsFromUpstreamJson method of BaseWatch', () => { diff --git a/x-pack/plugins/watcher/server/models/watch/__tests__/threshold_watch.js b/x-pack/plugins/watcher/server/models/watch/__tests__/threshold_watch.js index 46d9a6d699a798..ed99ff6a84da86 100644 --- a/x-pack/plugins/watcher/server/models/watch/__tests__/threshold_watch.js +++ b/x-pack/plugins/watcher/server/models/watch/__tests__/threshold_watch.js @@ -111,7 +111,7 @@ describe('ThresholdWatch', () => { let props; beforeEach(() => { - constructorMock.reset(); + constructorMock.resetHistory(); props = { index: 'index', @@ -195,12 +195,12 @@ describe('ThresholdWatch', () => { describe('watchJson getter method', () => { beforeEach(() => { - buildActionsMock.reset(); - buildConditionMock.reset(); - buildInputMock.reset(); - buildMetadataMock.reset(); - buildTransformMock.reset(); - buildTriggerMock.reset(); + buildActionsMock.resetHistory(); + buildConditionMock.resetHistory(); + buildInputMock.resetHistory(); + buildMetadataMock.resetHistory(); + buildTransformMock.resetHistory(); + buildTriggerMock.resetHistory(); }); it('should return the correct result', () => { @@ -229,7 +229,7 @@ describe('ThresholdWatch', () => { describe('getVisualizeQuery method', () => { beforeEach(() => { - buildVisualizeQueryMock.reset(); + buildVisualizeQueryMock.resetHistory(); }); it('should call the external buildVisualizeQuery method', () => { @@ -245,7 +245,7 @@ describe('ThresholdWatch', () => { describe('formatVisualizeData method', () => { beforeEach(() => { - formatVisualizeDataMock.reset(); + formatVisualizeDataMock.resetHistory(); }); it('should call the external formatVisualizeData method', () => { @@ -262,7 +262,7 @@ describe('ThresholdWatch', () => { let props; beforeEach(() => { - upstreamJsonMock.reset(); + upstreamJsonMock.resetHistory(); props = { index: 'index', @@ -295,7 +295,7 @@ describe('ThresholdWatch', () => { let props; beforeEach(() => { - downstreamJsonMock.reset(); + downstreamJsonMock.resetHistory(); props = { index: 'index', @@ -342,7 +342,7 @@ describe('ThresholdWatch', () => { let upstreamJson; beforeEach(() => { - getPropsFromUpstreamJsonMock.reset(); + getPropsFromUpstreamJsonMock.resetHistory(); upstreamJson = { watchJson: { @@ -399,7 +399,7 @@ describe('ThresholdWatch', () => { let downstreamJson; beforeEach(() => { - getPropsFromDownstreamJsonMock.reset(); + getPropsFromDownstreamJsonMock.resetHistory(); downstreamJson = { index: 'index', diff --git a/x-pack/plugins/watcher/server/models/watch/__tests__/watch.js b/x-pack/plugins/watcher/server/models/watch/__tests__/watch.js index d91fd150de3c20..ac186b3846579b 100644 --- a/x-pack/plugins/watcher/server/models/watch/__tests__/watch.js +++ b/x-pack/plugins/watcher/server/models/watch/__tests__/watch.js @@ -60,7 +60,7 @@ describe('Watch', () => { beforeEach(() => { Object.keys(watchTypeMocks).forEach(key => { - watchTypeMocks[key].fromDownstreamJsonMock.reset(); + watchTypeMocks[key].fromDownstreamJsonMock.resetHistory(); }); }); @@ -95,7 +95,7 @@ describe('Watch', () => { beforeEach(() => { Object.keys(watchTypeMocks).forEach(key => { - watchTypeMocks[key].fromUpstreamJsonMock.reset(); + watchTypeMocks[key].fromUpstreamJsonMock.resetHistory(); }); }); diff --git a/x-pack/plugins/xpack_main/common/constants.js b/x-pack/plugins/xpack_main/common/constants.js index 93f193c02435ec..d939038a3986b1 100644 --- a/x-pack/plugins/xpack_main/common/constants.js +++ b/x-pack/plugins/xpack_main/common/constants.js @@ -23,6 +23,12 @@ export const CONFIG_TELEMETRY_DESC = ( */ export const KIBANA_SYSTEM_ID = 'kibana'; +/** + * The name of the Beats System ID used to publish and look up Beats stats through the Monitoring system. + * @type {string} + */ +export const BEATS_SYSTEM_ID = 'beats'; + /** * The name of the Kibana System ID used to look up Logstash stats through the Monitoring system. * @type {string} diff --git a/x-pack/plugins/xpack_main/index.js b/x-pack/plugins/xpack_main/index.js index 4714929cd88400..92d300c8821861 100644 --- a/x-pack/plugins/xpack_main/index.js +++ b/x-pack/plugins/xpack_main/index.js @@ -15,6 +15,7 @@ import { replaceInjectedVars } from './server/lib/replace_injected_vars'; import { setupXPackMain } from './server/lib/setup_xpack_main'; import { xpackInfoRoute, + xpackUsageRoute, kibanaStatsRoute, telemetryRoute, } from './server/routes/api/v1'; @@ -67,12 +68,14 @@ export const xpackMain = (kibana) => { uiExports: { uiSettingDefaults: { [CONFIG_TELEMETRY]: { + name: 'Telemetry opt-in', description: CONFIG_TELEMETRY_DESC, value: false }, [XPACK_DEFAULT_ADMIN_EMAIL_UI_SETTING]: { + name: 'Admin email', // TODO: change the description when email address is used for more things? - description: 'Recipient email address for X-Pack admin operations, such as Cluster Alert email notifications from Monitoring.', + description: `Recipient email address for X-Pack admin operations, such as Cluster Alert email notifications from Monitoring.`, type: 'string', // TODO: Any way of ensuring this is a valid email address? value: null } @@ -108,7 +111,8 @@ export const xpackMain = (kibana) => { // register routes xpackInfoRoute(server); - kibanaStatsRoute(server); + xpackUsageRoute(server); // To replace kibanaStatsRoute + kibanaStatsRoute(server); // Only used internally. Remove in the next major. telemetryRoute(server); } }); diff --git a/x-pack/plugins/xpack_main/public/hacks/__tests__/check_xpack_info_change.js b/x-pack/plugins/xpack_main/public/hacks/__tests__/check_xpack_info_change.js index a3304a1b12b33b..a3cb4dfd8cdf54 100644 --- a/x-pack/plugins/xpack_main/public/hacks/__tests__/check_xpack_info_change.js +++ b/x-pack/plugins/xpack_main/public/hacks/__tests__/check_xpack_info_change.js @@ -12,7 +12,7 @@ const XPACK_INFO_SIG_KEY = 'xpackMain.infoSignature'; const XPACK_INFO_KEY = 'xpackMain.info'; describe('CheckXPackInfoChange Factory', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); let mockSessionStorage; beforeEach(ngMock.module('kibana', ($provide) => { @@ -95,7 +95,7 @@ describe('CheckXPackInfoChange Factory', () => { }); // If license didn't change banner shouldn't be displayed. - Notifier.prototype.directive.reset(); + Notifier.prototype.directive.resetHistory(); mockSessionStorage.getItem.withArgs(XPACK_INFO_SIG_KEY).returns('bar'); $http.post('/api/test'); diff --git a/x-pack/plugins/xpack_main/public/hacks/welcome_banner/opt_in_banner_component.js b/x-pack/plugins/xpack_main/public/hacks/welcome_banner/opt_in_banner_component.js index bf3e2e3b38ae5a..805a9541191f56 100644 --- a/x-pack/plugins/xpack_main/public/hacks/welcome_banner/opt_in_banner_component.js +++ b/x-pack/plugins/xpack_main/public/hacks/welcome_banner/opt_in_banner_component.js @@ -102,7 +102,6 @@ export class OptInBanner extends Component { this.props.optInClick(true)} > Yes diff --git a/x-pack/plugins/xpack_main/server/lib/__tests__/setup_xpack_main.js b/x-pack/plugins/xpack_main/server/lib/__tests__/setup_xpack_main.js index 2a71b1a9dfd733..c3bb9ccc5b21c6 100644 --- a/x-pack/plugins/xpack_main/server/lib/__tests__/setup_xpack_main.js +++ b/x-pack/plugins/xpack_main/server/lib/__tests__/setup_xpack_main.js @@ -10,7 +10,7 @@ import { setupXPackMain } from '../setup_xpack_main'; import * as InjectXPackInfoSignatureNS from '../inject_xpack_info_signature'; describe('setupXPackMain()', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); let mockServer; let mockElasticsearchPlugin; @@ -58,7 +58,7 @@ describe('setupXPackMain()', () => { sinon.assert.calledWithExactly(mockServer.expose, 'info', sinon.match.instanceOf(XPackInfo)); sinon.assert.calledWithExactly(mockServer.ext, 'onPreResponse', sinon.match.func); - sinon.assert.calledWithExactly(mockElasticsearchPlugin.status.on, 'change', sinon.match.typeOf('asyncfunction')); + sinon.assert.calledWithExactly(mockElasticsearchPlugin.status.on, 'change', sinon.match.func); }); it('onPreResponse hook calls `injectXPackInfoSignature` for every request.', () => { @@ -95,7 +95,7 @@ describe('setupXPackMain()', () => { sinon.stub(xPackInfo, 'isAvailable').returns(false); // We need this to make sure the code waits for `refreshNow` to complete before it tries // to access its properties. - sinon.stub(xPackInfo, 'refreshNow', () => { + sinon.stub(xPackInfo, 'refreshNow').callsFake(() => { return new Promise((resolve) => { xPackInfo.isAvailable.returns(true); resolve(); @@ -114,7 +114,7 @@ describe('setupXPackMain()', () => { // We need this to make sure the code waits for `refreshNow` to complete before it tries // to access its properties. - sinon.stub(xPackInfo, 'refreshNow', () => { + sinon.stub(xPackInfo, 'refreshNow').callsFake(() => { return new Promise((resolve) => { xPackInfo.isAvailable.returns(false); xPackInfo.unavailableReason.returns('Some weird error.'); diff --git a/x-pack/plugins/xpack_main/server/lib/__tests__/xpack_info.js b/x-pack/plugins/xpack_main/server/lib/__tests__/xpack_info.js index 2bbc9d98d8681c..4d896268d4d8a2 100644 --- a/x-pack/plugins/xpack_main/server/lib/__tests__/xpack_info.js +++ b/x-pack/plugins/xpack_main/server/lib/__tests__/xpack_info.js @@ -48,7 +48,7 @@ function getSignature(object) { } describe('XPackInfo', () => { - const sandbox = sinon.sandbox.create(); + const sandbox = sinon.createSandbox(); let mockServer; let mockElasticsearchCluster; @@ -188,7 +188,7 @@ describe('XPackInfo', () => { 'mode: gold | status: active | expiry date: ' ) ); - mockServer.log.reset(); + mockServer.log.resetHistory(); await xPackInfo.refreshNow(); @@ -212,7 +212,7 @@ describe('XPackInfo', () => { }); it('restarts the poller.', async () => { - mockElasticsearchCluster.callWithInternalUser.reset(); + mockElasticsearchCluster.callWithInternalUser.resetHistory(); sandbox.clock.tick(1499); sinon.assert.notCalled(mockElasticsearchCluster.callWithInternalUser); @@ -231,7 +231,7 @@ describe('XPackInfo', () => { sandbox.clock.tick(1499); await xPackInfo.refreshNow(); - mockElasticsearchCluster.callWithInternalUser.reset(); + mockElasticsearchCluster.callWithInternalUser.resetHistory(); // Since poller has been restarted, it should not be called now. sandbox.clock.tick(1); diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/fixtures/beats_stats_results.json b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/fixtures/beats_stats_results.json new file mode 100644 index 00000000000000..785cd715aab4d6 --- /dev/null +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/fixtures/beats_stats_results.json @@ -0,0 +1,11073 @@ +[ + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "W7hppdX7R229Oy3KQbZrTw", + "beats_stats": { + "beat": { + "host": "spicy.local", + "type": "metricbeat", + "version": "7.0.0-alpha1" + }, + "metrics": { + "libbeat": { + "output": { + "type": "elasticsearch" + }, + "pipeline": { + "events": { + "published": 1038 + } + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "W7hppdX7R229Oy3KQbZrTw", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "spicy.local" + }, + "metrics": { + "libbeat": { + "output": { + "type": "elasticsearch" + }, + "pipeline": { + "events": { + "published": 38690 + } + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "W7hppdX7R229Oy3KQbZrTw", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "spicy.local" + }, + "metrics": { + "libbeat": { + "output": { + "type": "elasticsearch" + }, + "pipeline": { + "events": { + "published": 26059 + } + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "W7hppdX7R229Oy3KQbZrTw", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "spicy.local" + }, + "metrics": { + "libbeat": { + "output": { + "type": "elasticsearch" + }, + "pipeline": { + "events": { + "published": 4518 + } + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "W7hppdX7R229Oy3KQbZrTw", + "beats_stats": { + "beat": { + "host": "spicy.local", + "type": "filebeat", + "version": "7.0.0-alpha1" + }, + "metrics": { + "libbeat": { + "output": { + "type": "elasticsearch" + }, + "pipeline": { + "events": { + "published": 10570 + } + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "filebeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1003 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "type": "filebeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 1879 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "beat": { + "version": "7.0.0-alpha1", + "host": "tsullivan.local", + "type": "metricbeat" + }, + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 4340 + } + }, + "output": { + "type": "elasticsearch" + } + } + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "winlogbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "duckbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "apm-server", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "sheepbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + { + "hits": { + "hits": [ + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "heartbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + }, + { + "_source": { + "cluster_uuid": "FlV4ckTxQ0a78hmBkzzc9A", + "beats_stats": { + "metrics": { + "libbeat": { + "pipeline": { + "events": { + "published": 17 + } + }, + "output": { + "type": "elasticsearch" + } + } + }, + "beat": { + "type": "cowbeat", + "version": "7.0.0-alpha1", + "host": "tsullivan.local" + } + } + } + } + ] + } + }, + {} +] diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_beats_stats.js b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_beats_stats.js new file mode 100644 index 00000000000000..147effc84ca7c3 --- /dev/null +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/__tests__/get_beats_stats.js @@ -0,0 +1,142 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { fetchBeatsStats, processResults } from '../get_beats_stats'; +import sinon from 'sinon'; +import expect from 'expect.js'; +import beatsStatsResultSet from './fixtures/beats_stats_results'; + +describe('Get Beats Stats', () => { + describe('fetchBeatsStats', () => { + const clusterUuids = ['aCluster', 'bCluster', 'cCluster']; + const start = 100; + const end = 200; + let server; + let callCluster; + + beforeEach(() => { + const getStub = { get: sinon.stub() }; + getStub.get + .withArgs('xpack.monitoring.beats.index_pattern') + .returns('beats-indices-*'); + server = { config: () => getStub }; + callCluster = sinon.stub(); + }); + + it('should set `from: 0, to: 10000` in the query', () => { + fetchBeatsStats(server, callCluster, clusterUuids, start, end); + const { args } = callCluster.firstCall; + const [api, { body }] = args; + + expect(api).to.be('search'); + expect(body.from).to.be(0); + expect(body.size).to.be(10000); + }); + + it('should set `from: 10000, from: 10000` in the query', () => { + fetchBeatsStats(server, callCluster, clusterUuids, start, end, { page: 1 }); + const { args } = callCluster.firstCall; + const [api, { body }] = args; + + expect(api).to.be('search'); + expect(body.from).to.be(10000); + expect(body.size).to.be(10000); + }); + + it('should set `from: 20000, from: 10000` in the query', () => { + fetchBeatsStats(server, callCluster, clusterUuids, start, end, { page: 2 }); + const { args } = callCluster.firstCall; + const [api, { body }] = args; + + expect(api).to.be('search'); + expect(body.from).to.be(20000); + expect(body.size).to.be(10000); + }); + }); + + describe('processResults', () => { + it('should summarize empty results', () => { + const resultsEmpty = undefined; + const clusters = {}; + const clusterHostMaps = {}; + + processResults(resultsEmpty, clusters, clusterHostMaps); + + expect(clusters).to.eql({}); + }); + + it('should summarize single result with some missing fields', () => { + const results = { + hits: { + hits: [ + { + _source: { + cluster_uuid: 'FlV4ckTxQ0a78hmBkzzc9A', + beats_stats: { + metrics: { libbeat: { output: { type: 'elasticsearch' } } }, // missing events published + beat: { type: 'cowbeat' }, // missing version and output + }, + }, + }, + ], + }, + }; + const clusters = {}; + const clusterHostMaps = {}; + processResults(results, clusters, clusterHostMaps); + + expect(clusters).to.eql({ + FlV4ckTxQ0a78hmBkzzc9A: { + count: 1, + versions: {}, + types: { cowbeat: 1 }, + outputs: { elasticsearch: 1 }, + eventsPublished: 0, + hosts: 0, + }, + }); + }); + + it('should summarize stats from hits across multiple result objects', () => { + + const clusters = {}; + const clusterHostMaps = {}; + + // beatsStatsResultSet is an array of many small query results + beatsStatsResultSet.forEach(results => { + processResults(results, clusters, clusterHostMaps); + }); + + expect(clusters).to.eql({ + W7hppdX7R229Oy3KQbZrTw: { + count: 5, + versions: { '7.0.0-alpha1': 5 }, + types: { metricbeat: 1, filebeat: 4 }, + outputs: { elasticsearch: 5 }, + eventsPublished: 80875, + hosts: 1, + }, + FlV4ckTxQ0a78hmBkzzc9A: { + count: 405, + versions: { '7.0.0-alpha1': 405 }, + types: { + filebeat: 200, + metricbeat: 100, + heartbeat: 100, + winlogbeat: 1, + duckbeat: 1, + 'apm-server': 1, + sheepbeat: 1, + cowbeat: 1, + }, + outputs: { elasticsearch: 405 }, + eventsPublished: 723985, + hosts: 1, + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/get_all_stats.js b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/get_all_stats.js index 67c95aa284f427..4770258003cbe2 100644 --- a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/get_all_stats.js +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/get_all_stats.js @@ -9,11 +9,13 @@ import { KIBANA_SYSTEM_ID, LOGSTASH_SYSTEM_ID, REPORTING_SYSTEM_ID, + BEATS_SYSTEM_ID, } from '../../../../common/constants'; import { getClusterUuids } from './get_cluster_uuids'; import { getElasticsearchStats } from './get_es_stats'; import { getKibanaStats } from './get_kibana_stats'; import { getReportingStats } from './get_reporting_stats'; +import { getBeatsStats } from './get_beats_stats'; import { getHighLevelStats } from './get_high_level_stats'; /** @@ -68,8 +70,9 @@ function getAllStatsWithCaller(server, callCluster, start, end) { getKibanaStats(server, callCluster, clusterUuids, start, end), // stack_stats.kibana getHighLevelStats(server, callCluster, clusterUuids, start, end, LOGSTASH_SYSTEM_ID), // stack_stats.logstash getReportingStats(server, callCluster, clusterUuids, start, end), // stack_stats.xpack.reporting + getBeatsStats(server, callCluster, clusterUuids, start, end), // stack_stats.beats ]) - .then(([esClusters, kibana, logstash, reporting]) => handleAllStats(esClusters, { kibana, logstash, reporting })); + .then(([esClusters, kibana, logstash, reporting, beats]) => handleAllStats(esClusters, { kibana, logstash, reporting, beats })); }); } @@ -82,12 +85,12 @@ function getAllStatsWithCaller(server, callCluster, start, end) { * @param {Object} logstash The Logstash nodes keyed by Cluster UUID * @return {Array} The clusters joined with the Kibana and Logstash instances under each cluster's {@code stack_stats}. */ -export function handleAllStats(clusters, { kibana, logstash, reporting }) { +export function handleAllStats(clusters, { kibana, logstash, reporting, beats }) { return clusters.map(cluster => { // if they are using Kibana or Logstash, then add it to the cluster details under cluster.stack_stats addStackStats(cluster, kibana, KIBANA_SYSTEM_ID); addStackStats(cluster, logstash, LOGSTASH_SYSTEM_ID); - + addStackStats(cluster, beats, BEATS_SYSTEM_ID); addXPackStats(cluster, reporting, REPORTING_SYSTEM_ID); mergeXPackStats(cluster, kibana, 'graph_workspace', 'graph'); // copy graph_workspace info out of kibana, merge it into stack_stats.xpack.graph diff --git a/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/get_beats_stats.js b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/get_beats_stats.js new file mode 100644 index 00000000000000..2928166bcf6a48 --- /dev/null +++ b/x-pack/plugins/xpack_main/server/lib/telemetry/monitoring/get_beats_stats.js @@ -0,0 +1,149 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { get } from 'lodash'; +import { createQuery } from './create_query'; + +const HITS_SIZE = 10000; // maximum hits to receive from ES with each search + +/* + * Create a set of result objects where each is the result of searching hits from Elasticsearch with a size of HITS_SIZE each time. + * @param {Object} server - The server instance + * @param {function} callCluster - The callWithRequest or callWithInternalUser handler + * @param {Array} clusterUuids - The string Cluster UUIDs to fetch details for + * @param {Date} start - Start time to limit the stats + * @param {Date} end - End time to limit the stats + * @param {Number} page - selection of hits to fetch from ES + * @param {Object} clusters - Beats stats in an object keyed by the cluster UUIDs + * @param {Object} clusterHostMaps - the object keyed by cluster UUIDs to count the unique hosts + * @return {Promise} + */ +export async function fetchBeatsStats( + server, callCluster, clusterUuids, start, end, + { page = 0, clusters, clusterHostMaps } = {} +) { + const config = server.config(); + + const params = { + index: config.get('xpack.monitoring.beats.index_pattern'), + ignoreUnavailable: true, + filterPath: [ + 'hits.hits._source.cluster_uuid', + 'hits.hits._source.beats_stats.beat.version', + 'hits.hits._source.beats_stats.beat.type', + 'hits.hits._source.beats_stats.beat.host', + 'hits.hits._source.beats_stats.metrics.libbeat.pipeline.events.published', + 'hits.hits._source.beats_stats.metrics.libbeat.output.type', + ], + body: { + query: createQuery({ + start, + end, + type: 'beats_stats', + filters: [ + { terms: { cluster_uuid: clusterUuids } }, + { bool: { must_not: { term: { 'beats_stats.beat.type': 'apm-server' } } } }, + ], + }), + collapse: { field: 'beats_stats.beat.uuid' }, + sort: [{ 'beats_stats.timestamp': 'desc' }], + from: page * HITS_SIZE, + size: HITS_SIZE, + }, + }; + + const results = await callCluster('search', params); + const hitsLength = get(results, 'hits.hits.length', 0); + if (hitsLength > 0) { + // further augment the clusters object with more stats + processResults(results, clusters, clusterHostMaps); + + if (hitsLength === HITS_SIZE) { + // call recursively + const nextOptions = { + clusters, + clusterHostMaps, + page: page + 1, + }; + + // returns a promise and keeps the caller blocked from returning until the entire clusters object is built + return fetchBeatsStats(server, callCluster, clusterUuids, start, end, nextOptions); + } + } + + return Promise.resolve(); +} + +const getBaseStats = () => ({ + count: 0, + versions: {}, + types: {}, + outputs: {}, + eventsPublished: 0, + hosts: 0, +}); + +/* + * Update a clusters object with processed beat stats + * @param {Array} results - array of Beats docs from ES + * @param {Object} clusters - Beats stats in an object keyed by the cluster UUIDs + * @param {Object} clusterHostMaps - the object keyed by cluster UUIDs to count the unique hosts + */ +export function processResults(results = [], clusters, clusterHostMaps) { + const currHits = get(results, 'hits.hits', []); + currHits.forEach(hit => { + const clusterUuid = get(hit, '_source.cluster_uuid'); + if (clusters[clusterUuid] === undefined) { + clusters[clusterUuid] = getBaseStats(); + clusterHostMaps[clusterUuid] = new Map(); + } + + clusters[clusterUuid].count += 1; + + const { versions, types, outputs } = clusters[clusterUuid]; + + const thisVersion = get(hit, '_source.beats_stats.beat.version'); + if (thisVersion !== undefined) { + const thisVersionAccum = versions[thisVersion] || 0; + versions[thisVersion] = thisVersionAccum + 1; + } + + const thisType = get(hit, '_source.beats_stats.beat.type'); + if (thisType !== undefined) { + const thisTypeAccum = types[thisType] || 0; + types[thisType] = thisTypeAccum + 1; + } + + const thisOutput = get(hit, '_source.beats_stats.metrics.libbeat.output.type'); + if (thisOutput !== undefined) { + const thisOutputAccum = outputs[thisOutput] || 0; + outputs[thisOutput] = thisOutputAccum + 1; + } + + const thisEvents = get(hit, '_source.beats_stats.metrics.libbeat.pipeline.events.published'); + if (thisEvents !== undefined) { + clusters[clusterUuid].eventsPublished += thisEvents; + } + + const thisHost = get(hit, '_source.beats_stats.beat.host'); + if (thisHost !== undefined) { + const hostsMap = clusterHostMaps[clusterUuid]; + hostsMap.set(thisHost, thisHost); // values don't matter, as this data structure is not part of the output + clusters[clusterUuid].hosts = hostsMap.size; + } + }); +} + +/* + * Call the function for fetching and summarizing beats stats + * @return {Object} - Beats stats in an object keyed by the cluster UUIDs + */ +export async function getBeatsStats(server, callCluster, clusterUuids, start, end) { + const clusters = {}; + const clusterHostMaps = {}; + await fetchBeatsStats(server, callCluster, clusterUuids, start, end, { clusters, clusterHostMaps }); + return clusters; +} diff --git a/x-pack/plugins/xpack_main/server/lib/xpack_info.js b/x-pack/plugins/xpack_main/server/lib/xpack_info.js index 105f31782a8535..c1146295544391 100644 --- a/x-pack/plugins/xpack_main/server/lib/xpack_info.js +++ b/x-pack/plugins/xpack_main/server/lib/xpack_info.js @@ -6,7 +6,7 @@ import { createHash } from 'crypto'; import moment from 'moment'; -import { get } from 'lodash'; +import { get, has } from 'lodash'; import { Poller } from '../../../../common/poller'; import { XPackInfoLicense } from './xpack_info_license'; @@ -117,11 +117,17 @@ export class XPackInfo { }); if (this._hasLicenseInfoChanged(response)) { - const licenseInfo = [ + const licenseInfoParts = [ `mode: ${get(response, 'license.mode')}`, `status: ${get(response, 'license.status')}`, - `expiry date: ${moment(get(response, 'license.expiry_date_in_millis'), 'x').format()}` - ].join(' | '); + ]; + + if (has(response, 'license.expiry_date_in_millis')) { + const expiryDate = moment(response.license.expiry_date_in_millis, 'x').format(); + licenseInfoParts.push(`expiry date: ${expiryDate}`); + } + + const licenseInfo = licenseInfoParts.join(' | '); this._log( ['license', 'info', 'xpack'], diff --git a/x-pack/plugins/xpack_main/server/lib/xpack_info_license.js b/x-pack/plugins/xpack_main/server/lib/xpack_info_license.js index 8ba81d24b3b39f..b87bae9e403dde 100644 --- a/x-pack/plugins/xpack_main/server/lib/xpack_info_license.js +++ b/x-pack/plugins/xpack_main/server/lib/xpack_info_license.js @@ -39,6 +39,9 @@ export class XPackInfoLicense { /** * Returns license expiration date in ms. + * + * Note: A basic license created after 6.3 will have no expiration, thus returning undefined. + * * @returns {number|undefined} */ getExpiryDateInMillis() { @@ -47,7 +50,7 @@ export class XPackInfoLicense { /** * Checks if the license is represented in a specified license list. - * @param candidateLicenses List of the licenses to check against. + * @param {String} candidateLicenses List of the licenses to check against. * @returns {boolean} */ isOneOf(candidateLicenses) { @@ -65,4 +68,46 @@ export class XPackInfoLicense { getType() { return get(this._getRawLicense(), 'type'); } + + /** + * Returns mode of the license (basic, gold etc.). This is the "effective" type of the license. + * @returns {string|undefined} + */ + getMode() { + return get(this._getRawLicense(), 'mode'); + } + + /** + * Determine if the current license is active and the supplied {@code type}. + * + * @param {Function} typeChecker The license type checker. + * @returns {boolean} + */ + isActiveLicense(typeChecker) { + const license = this._getRawLicense(); + + return get(license, 'status') === 'active' && typeChecker(get(license, 'mode')); + } + + /** + * Determine if the license is an active, basic license. + * + * Note: This also verifies that the license is active. Therefore it is not safe to assume that !isBasic() === isNotBasic(). + * + * @returns {boolean} + */ + isBasic() { + return this.isActiveLicense(mode => mode === 'basic'); + } + + /** + * Determine if the license is an active, non-basic license (e.g., standard, gold, platinum, or trial). + * + * Note: This also verifies that the license is active. Therefore it is not safe to assume that !isBasic() === isNotBasic(). + * + * @returns {boolean} + */ + isNotBasic() { + return this.isActiveLicense(mode => mode !== 'basic'); + } } diff --git a/x-pack/plugins/xpack_main/server/lib/xpack_info_license.test.js b/x-pack/plugins/xpack_main/server/lib/xpack_info_license.test.js new file mode 100644 index 00000000000000..300110744e9793 --- /dev/null +++ b/x-pack/plugins/xpack_main/server/lib/xpack_info_license.test.js @@ -0,0 +1,183 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { XPackInfoLicense } from './xpack_info_license'; + +function getXPackInfoLicense(getRawLicense) { + return new XPackInfoLicense(getRawLicense); +} + +describe('XPackInfoLicense', () => { + + const xpackInfoLicenseUndefined = getXPackInfoLicense(() => { }); + let xpackInfoLicense; + let getRawLicense; + + beforeEach(() => { + getRawLicense = jest.fn(); + xpackInfoLicense = getXPackInfoLicense(getRawLicense); + }); + + test('getUid returns uid field', () => { + const uid = 'abc123'; + + getRawLicense.mockReturnValue({ uid }); + + expect(xpackInfoLicense.getUid()).toBe(uid); + expect(getRawLicense).toHaveBeenCalledTimes(1); + + expect(xpackInfoLicenseUndefined.getUid()).toBe(undefined); + }); + + test('isActive returns true if status is active', () => { + getRawLicense.mockReturnValue({ status: 'active' }); + + expect(xpackInfoLicense.isActive()).toBe(true); + expect(getRawLicense).toHaveBeenCalledTimes(1); + }); + + test('isActive returns false if status is not active', () => { + getRawLicense.mockReturnValue({ status: 'aCtIvE' }); // needs to match exactly + + expect(xpackInfoLicense.isActive()).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(1); + + expect(xpackInfoLicenseUndefined.isActive()).toBe(false); + }); + + test('getExpiryDateInMillis returns expiry_date_in_millis', () => { + getRawLicense.mockReturnValue({ expiry_date_in_millis: 123 }); + + expect(xpackInfoLicense.getExpiryDateInMillis()).toBe(123); + expect(getRawLicense).toHaveBeenCalledTimes(1); + + expect(xpackInfoLicenseUndefined.getExpiryDateInMillis()).toBe(undefined); + }); + + test('isOneOf returns true of the mode includes one of the types', () => { + getRawLicense.mockReturnValue({ mode: 'platinum' }); + + expect(xpackInfoLicense.isOneOf('platinum')).toBe(true); + expect(getRawLicense).toHaveBeenCalledTimes(1); + + expect(xpackInfoLicense.isOneOf([ 'platinum' ])).toBe(true); + expect(getRawLicense).toHaveBeenCalledTimes(2); + expect(xpackInfoLicense.isOneOf([ 'gold', 'platinum' ])).toBe(true); + expect(getRawLicense).toHaveBeenCalledTimes(3); + expect(xpackInfoLicense.isOneOf([ 'platinum', 'gold' ])).toBe(true); + expect(getRawLicense).toHaveBeenCalledTimes(4); + expect(xpackInfoLicense.isOneOf([ 'basic', 'gold' ])).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(5); + expect(xpackInfoLicense.isOneOf([ 'basic' ])).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(6); + + expect(xpackInfoLicenseUndefined.isOneOf([ 'platinum', 'gold' ])).toBe(false); + }); + + test('getType returns the type', () => { + getRawLicense.mockReturnValue({ type: 'basic' }); + + expect(xpackInfoLicense.getType()).toBe('basic'); + expect(getRawLicense).toHaveBeenCalledTimes(1); + + getRawLicense.mockReturnValue({ type: 'gold' }); + + expect(xpackInfoLicense.getType()).toBe('gold'); + expect(getRawLicense).toHaveBeenCalledTimes(2); + + expect(xpackInfoLicenseUndefined.getType()).toBe(undefined); + }); + + test('getMode returns the mode', () => { + getRawLicense.mockReturnValue({ mode: 'basic' }); + + expect(xpackInfoLicense.getMode()).toBe('basic'); + expect(getRawLicense).toHaveBeenCalledTimes(1); + + getRawLicense.mockReturnValue({ mode: 'gold' }); + + expect(xpackInfoLicense.getMode()).toBe('gold'); + expect(getRawLicense).toHaveBeenCalledTimes(2); + + expect(xpackInfoLicenseUndefined.getMode()).toBe(undefined); + }); + + test('isActiveLicense returns the true if active and typeChecker matches', () => { + const expectAbc123 = type => type === 'abc123'; + + getRawLicense.mockReturnValue({ status: 'active', mode: 'abc123' }); + + expect(xpackInfoLicense.isActiveLicense(expectAbc123)).toBe(true); + expect(getRawLicense).toHaveBeenCalledTimes(1); + + getRawLicense.mockReturnValue({ status: 'NOTactive', mode: 'abc123' }); + + expect(xpackInfoLicense.isActiveLicense(expectAbc123)).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(2); + + getRawLicense.mockReturnValue({ status: 'NOTactive', mode: 'NOTabc123' }); + + expect(xpackInfoLicense.isActiveLicense(expectAbc123)).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(3); + + getRawLicense.mockReturnValue({ status: 'active', mode: 'NOTabc123' }); + + expect(xpackInfoLicense.isActiveLicense(expectAbc123)).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(4); + + expect(xpackInfoLicenseUndefined.isActive(expectAbc123)).toBe(false); + }); + + test('isBasic returns the true if active and basic', () => { + getRawLicense.mockReturnValue({ status: 'active', mode: 'basic' }); + + expect(xpackInfoLicense.isBasic()).toBe(true); + expect(getRawLicense).toHaveBeenCalledTimes(1); + + getRawLicense.mockReturnValue({ status: 'NOTactive', mode: 'gold' }); + + expect(xpackInfoLicense.isBasic()).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(2); + + getRawLicense.mockReturnValue({ status: 'NOTactive', mode: 'trial' }); + + expect(xpackInfoLicense.isBasic()).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(3); + + getRawLicense.mockReturnValue({ status: 'active', mode: 'platinum' }); + + expect(xpackInfoLicense.isBasic()).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(4); + + expect(xpackInfoLicenseUndefined.isBasic()).toBe(false); + }); + + + test('isNotBasic returns the true if active and not basic', () => { + getRawLicense.mockReturnValue({ status: 'active', mode: 'platinum' }); + + expect(xpackInfoLicense.isNotBasic()).toBe(true); + expect(getRawLicense).toHaveBeenCalledTimes(1); + + getRawLicense.mockReturnValue({ status: 'NOTactive', mode: 'gold' }); + + expect(xpackInfoLicense.isNotBasic()).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(2); + + getRawLicense.mockReturnValue({ status: 'NOTactive', mode: 'trial' }); + + expect(xpackInfoLicense.isNotBasic()).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(3); + + getRawLicense.mockReturnValue({ status: 'active', mode: 'basic' }); + + expect(xpackInfoLicense.isNotBasic()).toBe(false); + expect(getRawLicense).toHaveBeenCalledTimes(4); + + expect(xpackInfoLicenseUndefined.isNotBasic()).toBe(false); + }); + +}); diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js b/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js index f5316a67c97def..06f5b8885f7dd5 100644 --- a/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/__tests__/xpack_info.js @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import Boom from 'boom'; import sinon from 'sinon'; import { xpackInfoRoute } from '../xpack_info'; @@ -43,7 +42,11 @@ describe('XPackInfo routes', () => { sinon.assert.calledWithExactly( replyStub, - Boom.notFound() + sinon.match({ + isBoom: true, + message: 'Not Found', + output: { statusCode: 404 }, + }) ); }); diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/index.js b/x-pack/plugins/xpack_main/server/routes/api/v1/index.js index 4f98b3220db2e5..9bedeaf371e291 100644 --- a/x-pack/plugins/xpack_main/server/routes/api/v1/index.js +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/index.js @@ -6,4 +6,5 @@ export { xpackInfoRoute } from './xpack_info'; export { kibanaStatsRoute } from './kibana_stats'; -export { telemetryRoute } from './telemetry'; \ No newline at end of file +export { xpackUsageRoute } from './xpack_usage'; +export { telemetryRoute } from './telemetry'; diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/kibana_stats.js b/x-pack/plugins/xpack_main/server/routes/api/v1/kibana_stats.js index f97f5b3e846911..94a35e657003a0 100644 --- a/x-pack/plugins/xpack_main/server/routes/api/v1/kibana_stats.js +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/kibana_stats.js @@ -4,9 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +/* + * TODO: deprecate this API in 7.0 + */ import { wrap } from 'boom'; import { callClusterFactory } from '../../../lib/call_cluster_factory'; -import { getUsageCollector, getReportingCollector } from '../../../../../monitoring/server/kibana_monitoring'; +import { getKibanaUsageCollector } from '../../../../../monitoring/server/kibana_monitoring'; +import { getReportingUsageCollector } from '../../../../../reporting/server/usage'; export function kibanaStatsRoute(server) { server.route({ @@ -18,12 +22,12 @@ export function kibanaStatsRoute(server) { const callCluster = callClusterFactory(server).getCallClusterWithReq(req); try { - const kibanaUsageCollector = getUsageCollector(server, callCluster); - const reportingCollector = getReportingCollector(server, callCluster); + const kibanaUsageCollector = getKibanaUsageCollector(server, callCluster); + const reportingUsageCollector = getReportingUsageCollector(server, callCluster); const [ kibana, reporting ] = await Promise.all([ kibanaUsageCollector.fetch(), - reportingCollector.fetch(), + reportingUsageCollector.fetch(), ]); reply({ diff --git a/x-pack/plugins/xpack_main/server/routes/api/v1/xpack_usage.js b/x-pack/plugins/xpack_main/server/routes/api/v1/xpack_usage.js new file mode 100644 index 00000000000000..9bf0ddf5ab873d --- /dev/null +++ b/x-pack/plugins/xpack_main/server/routes/api/v1/xpack_usage.js @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { wrap, serverTimeout as serverUnavailable } from 'boom'; + +const getClusterUuid = async req => { + const { server } = req; + const { callWithRequest, } = server.plugins.elasticsearch.getCluster('data'); + const { cluster_uuid: uuid } = await callWithRequest(req, 'info', { filterPath: 'cluster_uuid', }); + return uuid; +}; + +/* + * @return {Object} data from usage stats collectors registered with Monitoring CollectorSet + * @throws {Error} if the Monitoring CollectorSet is not ready + */ +const getUsage = async req => { + const server = req.server; + const { collectorSet } = server.plugins.monitoring; + if (collectorSet === undefined) { + const error = new Error('CollectorSet from Monitoring plugin is not ready for collecting usage'); // moving kibana_monitoring lib to xpack_main will make this unnecessary + throw serverUnavailable(error); + } + return collectorSet.bulkFetchUsage(); +}; + +export function xpackUsageRoute(server) { + server.route({ + path: '/api/_xpack/usage', + method: 'GET', + async handler(req, reply) { + try { + const [ clusterUuid, xpackUsage ] = await Promise.all([ + getClusterUuid(req), + getUsage(req), + ]); + + reply({ + cluster_uuid: clusterUuid, + ...xpackUsage + }); + } catch(err) { + req.log(['error'], err); + if (err.isBoom) { + reply(err); + } else { + reply(wrap(err, err.statusCode, err.message)); + } + } + } + }); +} diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js index 546d8baa78fc18..a7804100c52cbd 100644 --- a/x-pack/scripts/functional_tests.js +++ b/x-pack/scripts/functional_tests.js @@ -5,4 +5,8 @@ */ require('@kbn/plugin-helpers').babelRegister(); -require('../dev-tools/functional_tests').runFunctionTests(); +require('@kbn/test').runTestsCli([ + require.resolve('../test/functional/config.js'), + require.resolve('../test/api_integration/config.js'), + require.resolve('../test/saml_api_integration/config.js'), +]); diff --git a/x-pack/scripts/functional_tests_server.js b/x-pack/scripts/functional_tests_server.js index ebf21c320ac502..c361f1839c50b7 100644 --- a/x-pack/scripts/functional_tests_server.js +++ b/x-pack/scripts/functional_tests_server.js @@ -5,4 +5,6 @@ */ require('@kbn/plugin-helpers').babelRegister(); -require('../dev-tools/functional_tests').runFunctionalTestsServer(); +require('@kbn/test').startServersCli( + require.resolve('../test/functional/config.js'), +); diff --git a/x-pack/server/lib/audit_logger.test.js b/x-pack/server/lib/audit_logger.test.js new file mode 100644 index 00000000000000..146403f58c66ff --- /dev/null +++ b/x-pack/server/lib/audit_logger.test.js @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { AuditLogger } from './audit_logger'; + +test(`calls server.log with 'info', audit', pluginId and eventType as tags`, () => { + const mockServer = { + log: jest.fn() + }; + const pluginId = 'foo'; + const auditLogger = new AuditLogger(mockServer, pluginId); + + const eventType = 'bar'; + auditLogger.log(eventType, ''); + expect(mockServer.log).toHaveBeenCalledTimes(1); + expect(mockServer.log).toHaveBeenCalledWith(['info', 'audit', pluginId, eventType], expect.anything()); +}); + + +test(`calls server.log with message as tmpl`, () => { + const mockServer = { + log: jest.fn() + }; + + const auditLogger = new AuditLogger(mockServer, 'foo'); + + const message = 'summary of what happened'; + auditLogger.log('bar', message); + expect(mockServer.log).toHaveBeenCalledTimes(1); + expect(mockServer.log).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ + tmpl: message + })); +}); + +test(`calls server.log with data appended to log message`, () => { + const mockServer = { + log: jest.fn() + }; + + const auditLogger = new AuditLogger(mockServer, 'foo'); + + const data = { + foo: 'yup', + bar: 'nah', + }; + + auditLogger.log('bar', 'summary of what happened', data); + expect(mockServer.log).toHaveBeenCalledTimes(1); + expect(mockServer.log).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ + foo: data.foo, + bar: data.bar, + })); +}); diff --git a/x-pack/test/api_integration/apis/monitoring/beats/detail.js b/x-pack/test/api_integration/apis/monitoring/beats/detail.js new file mode 100644 index 00000000000000..1af5277b653afd --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/beats/detail.js @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from 'expect.js'; +import beatDetailFixture from './fixtures/detail'; + +export default function ({ getService }) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('instance detail', () => { + const archive = 'monitoring/beats-with-restarted-instance'; + const timeRange = { + min: '2018-02-09T20:49:00Z', + max: '2018-02-09T21:50:00Z' + }; + + before('load archive', () => { + return esArchiver.load(archive); + }); + + after('unload archive', () => { + return esArchiver.unload(archive); + }); + + it('should summarize beat with metrics', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/fHJwISmKTFO8bj57oFBLUQ/beats/beat/60599a4f-8139-4251-b0b9-15866df34221') + .set('kbn-xsrf', 'xxx') + .send({ timeRange }) + .expect(200); + + expect(body).to.eql(beatDetailFixture); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/monitoring/beats/fixtures/detail.json b/x-pack/test/api_integration/apis/monitoring/beats/fixtures/detail.json new file mode 100644 index 00000000000000..ee28a5e7162edf --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/beats/fixtures/detail.json @@ -0,0 +1,1571 @@ +{ + "summary": { + "uuid": "60599a4f-8139-4251-b0b9-15866df34221", + "transportAddress": "spicy.local", + "version": "7.0.0-alpha1", + "name": "spicy.local", + "type": "Metricbeat", + "output": "Elasticsearch", + "configReloads": 0, + "uptime": 440261, + "eventsTotal": 11466, + "eventsEmitted": 11466, + "eventsDropped": 0, + "bytesWritten": 9564746 + }, + "metrics": { + "beat_event_rates": [ + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.pipeline.events.total", + "metricAgg": "max", + "label": "New", + "title": "Events Rate", + "description": "New events sent to the publishing pipeline", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 27.3 + ], + [ + 1518212610000, + 27.3 + ], + [ + 1518212640000, + 27.3 + ], + [ + 1518212670000, + 27.3 + ], + [ + 1518212700000, + 27.3 + ], + [ + 1518212730000, + 27.3 + ], + [ + 1518212760000, + 27.3 + ], + [ + 1518212790000, + 27.3 + ], + [ + 1518212820000, + 27.3 + ], + [ + 1518212850000, + 27.3 + ], + [ + 1518212880000, + 27.3 + ], + [ + 1518212910000, + 27.3 + ], + [ + 1518212940000, + 27.3 + ], + [ + 1518212970000, + 9.1 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.output.events.total", + "metricAgg": "max", + "label": "Emitted", + "title": "Events Rate", + "description": "Events processed by the output (including retries)", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 0 + ], + [ + 1518212610000, + 0 + ], + [ + 1518212640000, + 0 + ], + [ + 1518212670000, + 0 + ], + [ + 1518212700000, + 0 + ], + [ + 1518212730000, + 0 + ], + [ + 1518212760000, + 0 + ], + [ + 1518212790000, + 0 + ], + [ + 1518212820000, + 0 + ], + [ + 1518212850000, + 0 + ], + [ + 1518212880000, + 0 + ], + [ + 1518212910000, + 0 + ], + [ + 1518212940000, + 0 + ], + [ + 1518212970000, + 0 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.output.events.acked", + "metricAgg": "max", + "label": "Acknowledged", + "title": "Events Rate", + "description": "Events acknowledged by the output (includes events dropped by the output)", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 0 + ], + [ + 1518212610000, + 0 + ], + [ + 1518212640000, + 0 + ], + [ + 1518212670000, + 0 + ], + [ + 1518212700000, + 0 + ], + [ + 1518212730000, + 0 + ], + [ + 1518212760000, + 0 + ], + [ + 1518212790000, + 0 + ], + [ + 1518212820000, + 0 + ], + [ + 1518212850000, + 0 + ], + [ + 1518212880000, + 0 + ], + [ + 1518212910000, + 0 + ], + [ + 1518212940000, + 0 + ], + [ + 1518212970000, + 0 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.pipeline.events.published", + "metricAgg": "max", + "label": "Queued", + "title": "Events Rate", + "description": "Events added to the event pipeline queue", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 27.3 + ], + [ + 1518212610000, + 27.3 + ], + [ + 1518212640000, + 27.3 + ], + [ + 1518212670000, + 27.3 + ], + [ + 1518212700000, + 27.3 + ], + [ + 1518212730000, + 27.3 + ], + [ + 1518212760000, + 27.3 + ], + [ + 1518212790000, + 27.3 + ], + [ + 1518212820000, + 27.3 + ], + [ + 1518212850000, + 27.3 + ], + [ + 1518212880000, + 27.3 + ], + [ + 1518212910000, + 27.3 + ], + [ + 1518212940000, + 27.3 + ], + [ + 1518212970000, + 9.1 + ] + ] + } + ], + "beat_fail_rates": [ + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.pipeline.events.failed", + "metricAgg": "max", + "label": "Failed in Pipeline", + "title": "Fail Rates", + "description": "Failures that happened before event was added to the publishing pipeline (output was disabled or publisher client closed)", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 0 + ], + [ + 1518212610000, + 0 + ], + [ + 1518212640000, + 0 + ], + [ + 1518212670000, + 0 + ], + [ + 1518212700000, + 0 + ], + [ + 1518212730000, + 0 + ], + [ + 1518212760000, + 0 + ], + [ + 1518212790000, + 0 + ], + [ + 1518212820000, + 0 + ], + [ + 1518212850000, + 0 + ], + [ + 1518212880000, + 0 + ], + [ + 1518212910000, + 0 + ], + [ + 1518212940000, + 0 + ], + [ + 1518212970000, + 0 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.pipeline.events.dropped", + "metricAgg": "max", + "label": "Dropped in Pipeline", + "title": "Fail Rates", + "description": "Events that have been dropped after N retries (N = max_retries setting)", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 0 + ], + [ + 1518212610000, + 0 + ], + [ + 1518212640000, + 0 + ], + [ + 1518212670000, + 0 + ], + [ + 1518212700000, + 0 + ], + [ + 1518212730000, + 0 + ], + [ + 1518212760000, + 0 + ], + [ + 1518212790000, + 0 + ], + [ + 1518212820000, + 0 + ], + [ + 1518212850000, + 0 + ], + [ + 1518212880000, + 0 + ], + [ + 1518212910000, + 0 + ], + [ + 1518212940000, + 0 + ], + [ + 1518212970000, + 0 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.output.events.dropped", + "metricAgg": "max", + "label": "Dropped in Output", + "title": "Fail Rates", + "description": "(Fatal drop) Events dropped by the output as being \"invalid.\" The output still acknowledges the event for the Beat to remove it from the queue.", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 0 + ], + [ + 1518212610000, + 0 + ], + [ + 1518212640000, + 0 + ], + [ + 1518212670000, + 0 + ], + [ + 1518212700000, + 0 + ], + [ + 1518212730000, + 0 + ], + [ + 1518212760000, + 0 + ], + [ + 1518212790000, + 0 + ], + [ + 1518212820000, + 0 + ], + [ + 1518212850000, + 0 + ], + [ + 1518212880000, + 0 + ], + [ + 1518212910000, + 0 + ], + [ + 1518212940000, + 0 + ], + [ + 1518212970000, + 0 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.pipeline.events.retry", + "metricAgg": "max", + "label": "Retry in Pipeline", + "title": "Fail Rates", + "description": "Events in the pipeline that are trying again to be sent to the output", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 0 + ], + [ + 1518212610000, + 0 + ], + [ + 1518212640000, + 0 + ], + [ + 1518212670000, + 0 + ], + [ + 1518212700000, + 0 + ], + [ + 1518212730000, + 0 + ], + [ + 1518212760000, + 0 + ], + [ + 1518212790000, + 0 + ], + [ + 1518212820000, + 0 + ], + [ + 1518212850000, + 0 + ], + [ + 1518212880000, + 0 + ], + [ + 1518212910000, + 0 + ], + [ + 1518212940000, + 0 + ], + [ + 1518212970000, + 0 + ] + ] + } + ], + "beat_throughput_rates": [ + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.output.write.bytes", + "metricAgg": "max", + "label": "Bytes Sent", + "title": "Throughput", + "description": "Bytes written to the output (consists of size of network headers and compressed payload)", + "units": "/s", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 22857.166666666668 + ], + [ + 1518212610000, + 21809.833333333332 + ], + [ + 1518212640000, + 23896.066666666666 + ], + [ + 1518212670000, + 23110.5 + ], + [ + 1518212700000, + 17254.266666666666 + ], + [ + 1518212730000, + 27146.233333333334 + ], + [ + 1518212760000, + 20635.933333333334 + ], + [ + 1518212790000, + 26116.2 + ], + [ + 1518212820000, + 23117.933333333334 + ], + [ + 1518212850000, + 17254.4 + ], + [ + 1518212880000, + 28442.8 + ], + [ + 1518212910000, + 19319.966666666667 + ], + [ + 1518212940000, + 26377.166666666668 + ], + [ + 1518212970000, + 5203.266666666666 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.output.read.bytes", + "metricAgg": "max", + "label": "Bytes Received", + "title": "Throughput", + "description": "Bytes read in response from the output", + "units": "/s", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 6281.033333333334 + ], + [ + 1518212610000, + 5900.266666666666 + ], + [ + 1518212640000, + 6661.766666666666 + ], + [ + 1518212670000, + 6661.9 + ], + [ + 1518212700000, + 4377.033333333334 + ], + [ + 1518212730000, + 7453.4 + ], + [ + 1518212760000, + 5925.9 + ], + [ + 1518212790000, + 7073.166666666667 + ], + [ + 1518212820000, + 6690.866666666667 + ], + [ + 1518212850000, + 4396.033333333334 + ], + [ + 1518212880000, + 8323.233333333334 + ], + [ + 1518212910000, + 4676.066666666667 + ], + [ + 1518212940000, + 7838.133333333333 + ], + [ + 1518212970000, + 1337.9 + ] + ] + } + ], + "beat_output_errors": [ + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.output.write.errors", + "metricAgg": "max", + "label": "Sending", + "title": "Output Errors", + "description": "Errors in writing the response from the output", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 0 + ], + [ + 1518212610000, + 0 + ], + [ + 1518212640000, + 0 + ], + [ + 1518212670000, + 0 + ], + [ + 1518212700000, + 0 + ], + [ + 1518212730000, + 0 + ], + [ + 1518212760000, + 0 + ], + [ + 1518212790000, + 0 + ], + [ + 1518212820000, + 0 + ], + [ + 1518212850000, + 0 + ], + [ + 1518212880000, + 0 + ], + [ + 1518212910000, + 0 + ], + [ + 1518212940000, + 0 + ], + [ + 1518212970000, + 0 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.libbeat.output.read.errors", + "metricAgg": "max", + "label": "Receiving", + "title": "Output Errors", + "description": "Errors in reading the response from the output", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 0 + ], + [ + 1518212610000, + 0 + ], + [ + 1518212640000, + 0 + ], + [ + 1518212670000, + 0 + ], + [ + 1518212700000, + 0 + ], + [ + 1518212730000, + 0 + ], + [ + 1518212760000, + 0 + ], + [ + 1518212790000, + 0 + ], + [ + 1518212820000, + 0 + ], + [ + 1518212850000, + 0 + ], + [ + 1518212880000, + 0 + ], + [ + 1518212910000, + 0 + ], + [ + 1518212940000, + 0 + ], + [ + 1518212970000, + 0 + ] + ] + } + ], + "beat_memory": [ + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.beat.memstats.memory_alloc", + "metricAgg": "max", + "label": "Active", + "title": "Memory", + "description": "Private memory in active use by the Beat", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1518212550000, + 7218840 + ], + [ + 1518212580000, + 5731608 + ], + [ + 1518212610000, + 7190216 + ], + [ + 1518212640000, + 7372128 + ], + [ + 1518212670000, + 6364000 + ], + [ + 1518212700000, + 6922392 + ], + [ + 1518212730000, + 8683016 + ], + [ + 1518212760000, + 6838576 + ], + [ + 1518212790000, + 8076536 + ], + [ + 1518212820000, + 6499144 + ], + [ + 1518212850000, + 7986856 + ], + [ + 1518212880000, + 6491704 + ], + [ + 1518212910000, + 7986632 + ], + [ + 1518212940000, + 7605664 + ], + [ + 1518212970000, + 7598304 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.beat.memstats.rss", + "metricAgg": "max", + "label": "Process Total", + "title": "Memory", + "description": "Resident set size of memory reserved by the Beat from the OS", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1518212550000, + 40939520 + ], + [ + 1518212580000, + 36126720 + ], + [ + 1518212610000, + 36188160 + ], + [ + 1518212640000, + 37097472 + ], + [ + 1518212670000, + 37257216 + ], + [ + 1518212700000, + 37171200 + ], + [ + 1518212730000, + 32886784 + ], + [ + 1518212760000, + 33087488 + ], + [ + 1518212790000, + 33058816 + ], + [ + 1518212820000, + 32894976 + ], + [ + 1518212850000, + 33087488 + ], + [ + 1518212880000, + 33218560 + ], + [ + 1518212910000, + 33243136 + ], + [ + 1518212940000, + 35459072 + ], + [ + 1518212970000, + 35471360 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.beat.memstats.gc_next", + "metricAgg": "max", + "label": "GC Next", + "title": "Memory", + "description": "Limit of allocated memory at which garbage collection will occur", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1518212550000, + 9444400 + ], + [ + 1518212580000, + 9334256 + ], + [ + 1518212610000, + 9752752 + ], + [ + 1518212640000, + 10073040 + ], + [ + 1518212670000, + 9931344 + ], + [ + 1518212700000, + 10466192 + ], + [ + 1518212730000, + 9876624 + ], + [ + 1518212760000, + 11007568 + ], + [ + 1518212790000, + 9953440 + ], + [ + 1518212820000, + 9833024 + ], + [ + 1518212850000, + 11066352 + ], + [ + 1518212880000, + 10439376 + ], + [ + 1518212910000, + 11023968 + ], + [ + 1518212940000, + 9470112 + ], + [ + 1518212970000, + 9983712 + ] + ] + } + ], + "beat_cpu_utilization": [ + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.beat.cpu.total.value", + "metricAgg": "max", + "label": "Total", + "title": "CPU Utilization", + "description": "Percentage of CPU time spent executing (user+kernel mode) for the Beat process", + "units": "%", + "format": "0.[00]", + "hasCalculation": true, + "isDerivative": true + }, + "data": [ + [ + 1518212550000, + null + ], + [ + 1518212580000, + 0 + ], + [ + 1518212610000, + 0 + ], + [ + 1518212640000, + 0 + ], + [ + 1518212670000, + 0 + ], + [ + 1518212700000, + 0 + ], + [ + 1518212730000, + 0 + ], + [ + 1518212760000, + 0 + ], + [ + 1518212790000, + 0 + ], + [ + 1518212820000, + 0 + ], + [ + 1518212850000, + 0 + ], + [ + 1518212880000, + 0 + ], + [ + 1518212910000, + 0 + ], + [ + 1518212940000, + 0 + ], + [ + 1518212970000, + 0 + ] + ] + } + ], + "beat_os_load": [ + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.system.load.1", + "metricAgg": "max", + "label": "1m", + "title": "System Load", + "description": "Load average over the last 1 minute", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1518212550000, + 3.8462 + ], + [ + 1518212580000, + 3.7266 + ], + [ + 1518212610000, + 3.5405 + ], + [ + 1518212640000, + 3.2588 + ], + [ + 1518212670000, + 3.3047 + ], + [ + 1518212700000, + 2.9639 + ], + [ + 1518212730000, + 2.8369 + ], + [ + 1518212760000, + 2.7363 + ], + [ + 1518212790000, + 2.5972 + ], + [ + 1518212820000, + 2.6816 + ], + [ + 1518212850000, + 2.918 + ], + [ + 1518212880000, + 2.8921 + ], + [ + 1518212910000, + 2.6353 + ], + [ + 1518212940000, + 3.0137 + ], + [ + 1518212970000, + 2.6235 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.system.load.5", + "metricAgg": "max", + "label": "5m", + "title": "System Load", + "description": "Load average over the last 5 minutes", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1518212550000, + 2.8774 + ], + [ + 1518212580000, + 2.9438 + ], + [ + 1518212610000, + 2.9321 + ], + [ + 1518212640000, + 2.9175 + ], + [ + 1518212670000, + 2.9595 + ], + [ + 1518212700000, + 2.9009 + ], + [ + 1518212730000, + 2.874 + ], + [ + 1518212760000, + 2.8389 + ], + [ + 1518212790000, + 2.7803 + ], + [ + 1518212820000, + 2.7627 + ], + [ + 1518212850000, + 2.8022 + ], + [ + 1518212880000, + 2.7988 + ], + [ + 1518212910000, + 2.7314 + ], + [ + 1518212940000, + 2.8057 + ], + [ + 1518212970000, + 2.729 + ] + ] + }, + { + "bucket_size": "30 seconds", + "timeRange": { + "min": 1518209340000, + "max": 1518213000000 + }, + "metric": { + "app": "beats", + "field": "beats_stats.metrics.system.load.15", + "metricAgg": "max", + "label": "15m", + "title": "System Load", + "description": "Load average over the last 15 minutes", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1518212550000, + 2.7319 + ], + [ + 1518212580000, + 2.7612 + ], + [ + 1518212610000, + 2.7612 + ], + [ + 1518212640000, + 2.7573 + ], + [ + 1518212670000, + 2.7773 + ], + [ + 1518212700000, + 2.7598 + ], + [ + 1518212730000, + 2.752 + ], + [ + 1518212760000, + 2.7427 + ], + [ + 1518212790000, + 2.7251 + ], + [ + 1518212820000, + 2.7192 + ], + [ + 1518212850000, + 2.7339 + ], + [ + 1518212880000, + 2.7339 + ], + [ + 1518212910000, + 2.7104 + ], + [ + 1518212940000, + 2.7368 + ], + [ + 1518212970000, + 2.7104 + ] + ] + } + ] + } +} diff --git a/x-pack/test/api_integration/apis/monitoring/beats/index.js b/x-pack/test/api_integration/apis/monitoring/beats/index.js index 95555e13f35a57..e8d404e83705ec 100644 --- a/x-pack/test/api_integration/apis/monitoring/beats/index.js +++ b/x-pack/test/api_integration/apis/monitoring/beats/index.js @@ -8,5 +8,6 @@ export default function ({ loadTestFile }) { describe('Beats', () => { loadTestFile(require.resolve('./overview')); loadTestFile(require.resolve('./list')); + loadTestFile(require.resolve('./detail')); }); } diff --git a/x-pack/test/api_integration/apis/monitoring/cluster/fixtures/multicluster.json b/x-pack/test/api_integration/apis/monitoring/cluster/fixtures/multicluster.json index 20502f5c38180b..259d3e962c594d 100644 --- a/x-pack/test/api_integration/apis/monitoring/cluster/fixtures/multicluster.json +++ b/x-pack/test/api_integration/apis/monitoring/cluster/fixtures/multicluster.json @@ -1,211 +1,74 @@ [ { - "alerts": { - "alertsMeta": { - "enabled": true - }, - "clusterMeta": { - "enabled": false, - "message": "Cluster [clustertwo] license type [basic] does not support Cluster Alerts" - } - }, - "beats": { - "beats": { - "total": null, - "types": [] - }, - "bytesSent": null, - "totalEvents": null - }, + "cluster_uuid": "6d-9tDFTRe-qT5GoBytdlQ", "cluster_name": "clustertwo", - "cluster_state": { - "master_node": "7Cw93cHFS9mLBojuYdd9EQ", - "nodes": { - "7Cw93cHFS9mLBojuYdd9EQ": { - "attributes": { - "ml.enabled": "true" - }, - "ephemeral_id": "39Xe_o2RR9uVBRAk5j6WOQ", - "name": "clustertwo-02", - "transport_address": "127.0.0.1:9304" - } - }, - "state_uuid": "L0nkstGcQpKQr1kZDgryAw", - "status": "green", - "version": 15 + "version": "7.0.0-alpha1", + "license": { + "status": "active", + "type": "basic", + "expiry_date_in_millis": 1914278399999 }, - "cluster_uuid": "6d-9tDFTRe-qT5GoBytdlQ", "elasticsearch": { "cluster_stats": { "indices": { - "completion": { - "size_in_bytes": 0 - }, "count": 1, "docs": { "count": 8, "deleted": 0 }, - "fielddata": { - "evictions": 0, - "memory_size_in_bytes": 0 - }, - "query_cache": { - "cache_count": 0, - "cache_size": 0, - "evictions": 0, - "hit_count": 0, - "memory_size_in_bytes": 0, - "miss_count": 0, - "total_count": 0 - }, - "segments": { - "count": 8, - "doc_values_memory_in_bytes": 680, - "file_sizes": {}, - "fixed_bit_set_memory_in_bytes": 0, - "index_writer_memory_in_bytes": 0, - "max_unsafe_auto_id_timestamp": -1, - "memory_in_bytes": 13852, - "norms_memory_in_bytes": 256, - "points_memory_in_bytes": 8, - "stored_fields_memory_in_bytes": 2496, - "term_vectors_memory_in_bytes": 0, - "terms_memory_in_bytes": 10412, - "version_map_memory_in_bytes": 0 - }, "shards": { + "total": 1, + "primaries": 1, + "replication": 0, "index": { + "shards": { + "min": 1, + "max": 1, + "avg": 1 + }, "primaries": { - "avg": 1, + "min": 1, "max": 1, - "min": 1 + "avg": 1 }, "replication": { - "avg": 0, + "min": 0, "max": 0, - "min": 0 - }, - "shards": { - "avg": 1, - "max": 1, - "min": 1 + "avg": 0 } - }, - "primaries": 1, - "replication": 0, - "total": 1 + } }, "store": { "size_in_bytes": 34095 } }, "nodes": { - "count": { - "coordinating_only": 0, - "data": 1, - "ingest": 1, - "master": 1, - "total": 1 - }, "fs": { - "available_in_bytes": 200403197952, + "total_in_bytes": 499065712640, "free_in_bytes": 200665341952, - "total_in_bytes": 499065712640 + "available_in_bytes": 200403197952 + }, + "count": { + "total": 1 }, "jvm": { "max_uptime_in_millis": 701043, "mem": { - "heap_max_in_bytes": 628555776, - "heap_used_in_bytes": 204299464 - }, - "threads": 40, - "versions": [ - { - "count": 1, - "version": "1.8.0_121", - "vm_name": "Java HotSpot(TM) 64-Bit Server VM", - "vm_vendor": "Oracle Corporation", - "vm_version": "25.121-b13" - } - ] - }, - "network_types": { - "http_types": { - "security4": 1 - }, - "transport_types": { - "security4": 1 + "heap_used_in_bytes": 204299464, + "heap_max_in_bytes": 628555776 } - }, - "os": { - "allocated_processors": 1, - "available_processors": 4, - "mem": { - "free_in_bytes": 183799808, - "free_percent": 1, - "total_in_bytes": 17179869184, - "used_in_bytes": 16996069376, - "used_percent": 99 - }, - "names": [ - { - "count": 1, - "name": "Mac OS X" - } - ] - }, - "plugins": [ - { - "classname": "org.elasticsearch.xpack.XPackPlugin", - "description": "Elasticsearch Expanded Pack Plugin", - "has_native_controller": true, - "name": "x-pack", - "version": "7.0.0-alpha1" - } - ], - "process": { - "cpu": { - "percent": 0 - }, - "open_file_descriptors": { - "avg": 163, - "max": 163, - "min": 163 - } - }, - "versions": [ - "7.0.0-alpha1" - ] + } }, - "status": "green", - "timestamp": 1502835059952 + "status": "green" } }, - "isPrimary": false, - "kibana": { - "concurrent_connections": 0, - "count": 0, - "memory_limit": 0, - "memory_size": 0, - "requests_total": 0, - "response_time_max": 0, - "status": null - }, - "license": { - "expiry_date": "2030-08-29T23:59:59.999Z", - "expiry_date_in_millis": 1914278399999, - "issue_date": "2014-09-29T00:00:00.000Z", - "status": "active", - "type": "basic" - }, "logstash": { - "avg_memory": 0, - "avg_memory_used": 0, + "node_count": 0, "events_in_total": 0, "events_out_total": 0, + "avg_memory": 0, + "avg_memory_used": 0, "max_uptime": 0, - "node_count": 0, "pipeline_count": 0, "queue_types": { "memory": 0, @@ -213,216 +76,106 @@ }, "versions": [] }, - "version": "7.0.0-alpha1" - }, - { - "alerts": { - "alertsMeta": { - "enabled": true - }, - "count": 1, - "high": 0, - "low": 0, - "medium": 1 + "kibana": { + "status": null, + "requests_total": 0, + "concurrent_connections": 0, + "response_time_max": 0, + "memory_size": 0, + "memory_limit": 0, + "count": 0 }, "beats": { + "totalEvents": null, + "bytesSent": null, "beats": { "total": null, "types": [] - }, - "bytesSent": null, - "totalEvents": null + } }, - "cluster_name": "monitoring-one", - "cluster_state": { - "master_node": "7r5cGj40Qcyia0J1xF0lnA", - "nodes": { - "7r5cGj40Qcyia0J1xF0lnA": { - "attributes": { - "ml.enabled": "true" - }, - "ephemeral_id": "9h7Asl78Riu-5BjLw7W9Tg", - "name": "monitoring-one-01", - "transport_address": "127.0.0.1:9300" - } + "alerts": { + "alertsMeta": { + "enabled": true }, - "state_uuid": "asE-gTxlRuad4K1ED5lNag", - "status": "yellow", - "version": 45 + "clusterMeta": { + "enabled": false, + "message": "Cluster [clustertwo] license type [basic] does not support Cluster Alerts" + } }, + "isPrimary": false, + "status": "green" + }, + { + "isSupported": true, "cluster_uuid": "lOF8kofiS_2DX58o9mXJ1Q", + "cluster_name": "monitoring-one", + "version": "7.0.0-alpha1", + "license": { + "status": "active", + "type": "trial", + "expiry_date_in_millis": 1505426308997 + }, "elasticsearch": { "cluster_stats": { "indices": { - "completion": { - "size_in_bytes": 0 - }, "count": 8, "docs": { "count": 3997, "deleted": 69 }, - "fielddata": { - "evictions": 0, - "memory_size_in_bytes": 2104 - }, - "query_cache": { - "cache_count": 0, - "cache_size": 0, - "evictions": 0, - "hit_count": 0, - "memory_size_in_bytes": 0, - "miss_count": 0, - "total_count": 0 - }, - "segments": { - "count": 36, - "doc_values_memory_in_bytes": 91352, - "file_sizes": {}, - "fixed_bit_set_memory_in_bytes": 992, - "index_writer_memory_in_bytes": 205347, - "max_unsafe_auto_id_timestamp": -1, - "memory_in_bytes": 278961, - "norms_memory_in_bytes": 6784, - "points_memory_in_bytes": 3250, - "stored_fields_memory_in_bytes": 11544, - "term_vectors_memory_in_bytes": 0, - "terms_memory_in_bytes": 166031, - "version_map_memory_in_bytes": 26362 - }, "shards": { + "total": 8, + "primaries": 8, + "replication": 0, "index": { + "shards": { + "min": 1, + "max": 1, + "avg": 1 + }, "primaries": { - "avg": 1, + "min": 1, "max": 1, - "min": 1 + "avg": 1 }, "replication": { - "avg": 0, + "min": 0, "max": 0, - "min": 0 - }, - "shards": { - "avg": 1, - "max": 1, - "min": 1 + "avg": 0 } - }, - "primaries": 8, - "replication": 0, - "total": 8 + } }, "store": { "size_in_bytes": 2647163 } }, "nodes": { - "count": { - "coordinating_only": 0, - "data": 1, - "ingest": 1, - "master": 1, - "total": 1 - }, "fs": { - "available_in_bytes": 200403648512, + "total_in_bytes": 499065712640, "free_in_bytes": 200665792512, - "total_in_bytes": 499065712640 + "available_in_bytes": 200403648512 + }, + "count": { + "total": 1 }, "jvm": { "max_uptime_in_millis": 761002, "mem": { - "heap_max_in_bytes": 628555776, - "heap_used_in_bytes": 133041176 - }, - "threads": 42, - "versions": [ - { - "count": 1, - "version": "1.8.0_121", - "vm_name": "Java HotSpot(TM) 64-Bit Server VM", - "vm_vendor": "Oracle Corporation", - "vm_version": "25.121-b13" - } - ] - }, - "network_types": { - "http_types": { - "security4": 1 - }, - "transport_types": { - "security4": 1 - } - }, - "os": { - "allocated_processors": 1, - "available_processors": 4, - "mem": { - "free_in_bytes": 86732800, - "free_percent": 1, - "total_in_bytes": 17179869184, - "used_in_bytes": 17093136384, - "used_percent": 99 - }, - "names": [ - { - "count": 1, - "name": "Mac OS X" - } - ] - }, - "plugins": [ - { - "classname": "org.elasticsearch.xpack.XPackPlugin", - "description": "Elasticsearch Expanded Pack Plugin", - "has_native_controller": true, - "name": "x-pack", - "version": "7.0.0-alpha1" + "heap_used_in_bytes": 133041176, + "heap_max_in_bytes": 628555776 } - ], - "process": { - "cpu": { - "percent": 2 - }, - "open_file_descriptors": { - "avg": 178, - "max": 178, - "min": 178 - } - }, - "versions": [ - "7.0.0-alpha1" - ] + } }, - "status": "yellow", - "timestamp": 1502835054610 + "status": "yellow" } }, - "isSupported": true, - "isPrimary": false, - "kibana": { - "concurrent_connections": 0, - "count": 0, - "memory_limit": 0, - "memory_size": 0, - "requests_total": 0, - "response_time_max": 0, - "status": null - }, - "license": { - "expiry_date": "2017-09-14T21:58:28.997Z", - "expiry_date_in_millis": 1505426308997, - "issue_date": "2017-08-15T21:58:28.997Z", - "status": "active", - "type": "trial" - }, "logstash": { - "avg_memory": 0, - "avg_memory_used": 0, + "node_count": 0, "events_in_total": 0, "events_out_total": 0, + "avg_memory": 0, + "avg_memory_used": 0, "max_uptime": 0, - "node_count": 0, "pipeline_count": 0, "queue_types": { "memory": 0, @@ -430,220 +183,106 @@ }, "versions": [] }, - "version": "7.0.0-alpha1" - }, - { - "alerts": { - "alertsMeta": { - "enabled": true - } + "kibana": { + "status": null, + "requests_total": 0, + "concurrent_connections": 0, + "response_time_max": 0, + "memory_size": 0, + "memory_limit": 0, + "count": 0 }, "beats": { + "totalEvents": null, + "bytesSent": null, "beats": { "total": null, "types": [] - }, - "bytesSent": null, - "totalEvents": null + } }, - "cluster_name": "clusterone", - "cluster_state": { - "master_node": "fYjS7QwxT42788axNXnZ1Q", - "nodes": { - "ZcUHP_QBQzeRjE5by3TbvQ": { - "attributes": { - "ml.enabled": "true" - }, - "ephemeral_id": "dkdHpjB2RIabMwbwcMWDNw", - "name": "clusterone-02", - "transport_address": "127.0.0.1:9303" - }, - "fYjS7QwxT42788axNXnZ1Q": { - "attributes": { - "ml.enabled": "true" - }, - "ephemeral_id": "gLCiGmfARciO6_8eTh9caw", - "name": "clusterone-01", - "transport_address": "127.0.0.1:9301" - } + "alerts": { + "alertsMeta": { + "enabled": true }, - "state_uuid": "v9cBtnUvQMqe_J-kAvZaBw", - "status": "green", - "version": 221 + "count": 1, + "low": 0, + "medium": 1, + "high": 0 }, + "isPrimary": false, + "status": "yellow" + }, + { + "isSupported": true, "cluster_uuid": "TkHOX_-1TzWwbROwQJU5IA", + "cluster_name": "clusterone", + "version": "7.0.0-alpha1", + "license": { + "status": "active", + "type": "trial", + "expiry_date_in_millis": 1505426327135 + }, "elasticsearch": { "cluster_stats": { "indices": { - "completion": { - "size_in_bytes": 0 - }, "count": 5, "docs": { "count": 150, "deleted": 0 }, - "fielddata": { - "evictions": 0, - "memory_size_in_bytes": 0 - }, - "query_cache": { - "cache_count": 0, - "cache_size": 0, - "evictions": 0, - "hit_count": 0, - "memory_size_in_bytes": 0, - "miss_count": 0, - "total_count": 0 - }, - "segments": { - "count": 76, - "doc_values_memory_in_bytes": 88064, - "file_sizes": {}, - "fixed_bit_set_memory_in_bytes": 0, - "index_writer_memory_in_bytes": 7006184, - "max_unsafe_auto_id_timestamp": 1502834982386, - "memory_in_bytes": 1907922, - "norms_memory_in_bytes": 197184, - "points_memory_in_bytes": 3818, - "stored_fields_memory_in_bytes": 23744, - "term_vectors_memory_in_bytes": 0, - "terms_memory_in_bytes": 1595112, - "version_map_memory_in_bytes": 260 - }, "shards": { + "total": 26, + "primaries": 13, + "replication": 1, "index": { + "shards": { + "min": 2, + "max": 10, + "avg": 5.2 + }, "primaries": { - "avg": 2.6, + "min": 1, "max": 5, - "min": 1 + "avg": 2.6 }, "replication": { - "avg": 1, + "min": 1, "max": 1, - "min": 1 - }, - "shards": { - "avg": 5.2, - "max": 10, - "min": 2 + "avg": 1 } - }, - "primaries": 13, - "replication": 1, - "total": 26 + } }, "store": { "size_in_bytes": 4838464 } }, "nodes": { - "count": { - "coordinating_only": 0, - "data": 2, - "ingest": 2, - "master": 2, - "total": 2 - }, "fs": { - "available_in_bytes": 200404209664, + "total_in_bytes": 499065712640, "free_in_bytes": 200666353664, - "total_in_bytes": 499065712640 + "available_in_bytes": 200404209664 + }, + "count": { + "total": 2 }, "jvm": { "max_uptime_in_millis": 741786, "mem": { - "heap_max_in_bytes": 1257111552, - "heap_used_in_bytes": 465621856 - }, - "threads": 92, - "versions": [ - { - "count": 2, - "version": "1.8.0_121", - "vm_name": "Java HotSpot(TM) 64-Bit Server VM", - "vm_vendor": "Oracle Corporation", - "vm_version": "25.121-b13" - } - ] - }, - "network_types": { - "http_types": { - "security4": 2 - }, - "transport_types": { - "security4": 2 + "heap_used_in_bytes": 465621856, + "heap_max_in_bytes": 1257111552 } - }, - "os": { - "allocated_processors": 2, - "available_processors": 8, - "mem": { - "free_in_bytes": 332099584, - "free_percent": 1, - "total_in_bytes": 34359738368, - "used_in_bytes": 34027638784, - "used_percent": 99 - }, - "names": [ - { - "count": 2, - "name": "Mac OS X" - } - ] - }, - "plugins": [ - { - "classname": "org.elasticsearch.xpack.XPackPlugin", - "description": "Elasticsearch Expanded Pack Plugin", - "has_native_controller": true, - "name": "x-pack", - "version": "7.0.0-alpha1" - } - ], - "process": { - "cpu": { - "percent": 2 - }, - "open_file_descriptors": { - "avg": 227, - "max": 237, - "min": 218 - } - }, - "versions": [ - "7.0.0-alpha1" - ] + } }, - "status": "green", - "timestamp": 1502835052641 + "status": "green" } }, - "isSupported": true, - "isPrimary": false, - "kibana": { - "concurrent_connections": 307, - "count": 1, - "memory_limit": 1501560832, - "memory_size": 231141376, - "requests_total": 571, - "response_time_max": 1930, - "status": "green" - }, - "license": { - "expiry_date": "2017-09-14T21:58:47.135Z", - "expiry_date_in_millis": 1505426327135, - "issue_date": "2017-08-15T21:58:47.135Z", - "status": "active", - "type": "trial" - }, "logstash": { - "avg_memory": 1038876672, - "avg_memory_used": 487782224, + "node_count": 1, "events_in_total": 142, "events_out_total": 142, + "avg_memory": 1038876672, + "avg_memory_used": 487782224, "max_uptime": 570039, - "node_count": 1, "pipeline_count": 1, "queue_types": { "memory": 1, @@ -653,7 +292,29 @@ "7.0.0-alpha1" ] }, - "version": "7.0.0-alpha1" + "kibana": { + "status": "green", + "requests_total": 571, + "concurrent_connections": 307, + "response_time_max": 1930, + "memory_size": 231141376, + "memory_limit": 1501560832, + "count": 1 + }, + "beats": { + "totalEvents": null, + "bytesSent": null, + "beats": { + "total": null, + "types": [] + } + }, + "alerts": { + "alertsMeta": { + "enabled": true + } + }, + "isPrimary": false, + "status": "green" } ] - diff --git a/x-pack/test/api_integration/apis/monitoring/cluster/fixtures/overview.json b/x-pack/test/api_integration/apis/monitoring/cluster/fixtures/overview.json index 66a5cc64eb6f2f..faa64e2c4cdb55 100644 --- a/x-pack/test/api_integration/apis/monitoring/cluster/fixtures/overview.json +++ b/x-pack/test/api_integration/apis/monitoring/cluster/fixtures/overview.json @@ -1,228 +1,74 @@ [ { - "alerts": [ - { - "message": "Allocate missing replica shards.", - "metadata": { - "alert_index": ".monitoring-alerts-6", - "cluster_uuid": "y1qOsQPiRrGtmdEuM3APJw", - "link": "elasticsearch/indices", - "severity": 1100, - "type": "monitoring", - "version_created": 6000026, - "watch": "elasticsearch_cluster_status" - }, - "prefix": "Elasticsearch cluster status is yellow.", - "resolved_timestamp": "2017-08-23T21:45:31.882Z", - "timestamp": "2017-08-23T21:28:25.639Z", - "update_timestamp": "2017-08-23T21:45:31.882Z" - } - ], - "beats": { - "beats": { - "total": null, - "types": [] - }, - "bytesSent": null, - "totalEvents": null - }, + "cluster_uuid": "y1qOsQPiRrGtmdEuM3APJw", "cluster_name": "singlecluster", - "cluster_state": { - "master_node": "ghLf1mWQRdiE8RQXA128UA", - "nodes": { - "ghLf1mWQRdiE8RQXA128UA": { - "attributes": { - "ml.enabled": "true" - }, - "ephemeral_id": "QX8nwLiQSbeI3WpDygHn-g", - "name": "single-01", - "transport_address": "127.0.0.1:9300" - }, - "ukb0scOOSNK_Vs4CoXKFTw": { - "attributes": { - "ml.enabled": "true" - }, - "ephemeral_id": "ALwCj74_SJCDkKVdCu9zMA", - "name": "single-02", - "transport_address": "127.0.0.1:9301" - } - }, - "state_uuid": "EDVQBaWPRpiHsEEcUeqYyA", - "status": "green", - "version": 140 + "version": "7.0.0-alpha1", + "license": { + "status": "active", + "type": "gold", + "expiry_date_in_millis": 1914278399999 }, - "cluster_uuid": "y1qOsQPiRrGtmdEuM3APJw", "elasticsearch": { "cluster_stats": { "indices": { - "completion": { - "size_in_bytes": 0 - }, "count": 17, "docs": { "count": 4001, "deleted": 99 }, - "fielddata": { - "evictions": 0, - "memory_size_in_bytes": 2496 - }, - "query_cache": { - "cache_count": 0, - "cache_size": 0, - "evictions": 0, - "hit_count": 0, - "memory_size_in_bytes": 0, - "miss_count": 0, - "total_count": 0 - }, - "segments": { - "count": 172, - "doc_values_memory_in_bytes": 365000, - "file_sizes": {}, - "fixed_bit_set_memory_in_bytes": 2752, - "index_writer_memory_in_bytes": 299400, - "max_unsafe_auto_id_timestamp": 1503524661506, - "memory_in_bytes": 3045776, - "norms_memory_in_bytes": 276480, - "points_memory_in_bytes": 8325, - "stored_fields_memory_in_bytes": 54080, - "term_vectors_memory_in_bytes": 0, - "terms_memory_in_bytes": 2341891, - "version_map_memory_in_bytes": 7690 - }, "shards": { + "total": 98, + "primaries": 49, + "replication": 1, "index": { + "shards": { + "min": 2, + "max": 10, + "avg": 5.764705882352941 + }, "primaries": { - "avg": 2.8823529411764706, + "min": 1, "max": 5, - "min": 1 + "avg": 2.8823529411764706 }, "replication": { - "avg": 1, + "min": 1, "max": 1, - "min": 1 - }, - "shards": { - "avg": 5.764705882352941, - "max": 10, - "min": 2 + "avg": 1 } - }, - "primaries": 49, - "replication": 1, - "total": 98 + } }, "store": { "size_in_bytes": 11826390 } }, "nodes": { - "count": { - "coordinating_only": 0, - "data": 2, - "ingest": 2, - "master": 2, - "total": 2 - }, "fs": { - "available_in_bytes": 201386397696, + "total_in_bytes": 499065712640, "free_in_bytes": 201648541696, - "total_in_bytes": 499065712640 + "available_in_bytes": 201386397696 + }, + "count": { + "total": 2 }, "jvm": { "max_uptime_in_millis": 1201658, "mem": { - "heap_max_in_bytes": 1257111552, - "heap_used_in_bytes": 551929768 - }, - "threads": 83, - "versions": [ - { - "count": 2, - "version": "1.8.0_121", - "vm_name": "Java HotSpot(TM) 64-Bit Server VM", - "vm_vendor": "Oracle Corporation", - "vm_version": "25.121-b13" - } - ] - }, - "network_types": { - "http_types": { - "security4": 2 - }, - "transport_types": { - "security4": 2 - } - }, - "os": { - "allocated_processors": 2, - "available_processors": 8, - "mem": { - "free_in_bytes": 85819392, - "free_percent": 0, - "total_in_bytes": 34359738368, - "used_in_bytes": 34273918976, - "used_percent": 100 - }, - "names": [ - { - "count": 2, - "name": "Mac OS X" - } - ] - }, - "plugins": [ - { - "classname": "org.elasticsearch.xpack.XPackPlugin", - "description": "Elasticsearch Expanded Pack Plugin", - "has_native_controller": true, - "name": "x-pack", - "version": "7.0.0-alpha1" + "heap_used_in_bytes": 551929768, + "heap_max_in_bytes": 1257111552 } - ], - "process": { - "cpu": { - "percent": 13 - }, - "open_file_descriptors": { - "avg": 304, - "max": 338, - "min": 270 - } - }, - "versions": [ - "7.0.0-alpha1" - ] + } }, - "status": "green", - "timestamp": 1503524825081 + "status": "green" } }, - "isPrimary": true, - "kibana": { - "concurrent_connections": 646, - "count": 1, - "memory_limit": 1501560832, - "memory_size": 196005888, - "requests_total": 914, - "response_time_max": 2873, - "status": "green" - }, - "license": { - "expiry_date": "2030-08-29T23:59:59.999Z", - "expiry_date_in_millis": 1914278399999, - "issue_date": "2014-09-29T00:00:00.000Z", - "status": "active", - "type": "gold" - }, "logstash": { - "avg_memory": 1038876672, - "avg_memory_used": 479515336, + "node_count": 1, "events_in_total": 31, "events_out_total": 31, + "avg_memory": 1038876672, + "avg_memory_used": 479515336, "max_uptime": 603966, - "node_count": 1, "pipeline_count": 1, "queue_types": { "memory": 1, @@ -232,6 +78,42 @@ "7.0.0-alpha1" ] }, - "version": "7.0.0-alpha1" + "kibana": { + "status": "green", + "requests_total": 914, + "concurrent_connections": 646, + "response_time_max": 2873, + "memory_size": 196005888, + "memory_limit": 1501560832, + "count": 1 + }, + "beats": { + "totalEvents": null, + "bytesSent": null, + "beats": { + "total": null, + "types": [] + } + }, + "alerts": [ + { + "metadata": { + "severity": 1100, + "cluster_uuid": "y1qOsQPiRrGtmdEuM3APJw", + "version_created": 6000026, + "watch": "elasticsearch_cluster_status", + "link": "elasticsearch/indices", + "alert_index": ".monitoring-alerts-6", + "type": "monitoring" + }, + "update_timestamp": "2017-08-23T21:45:31.882Z", + "prefix": "Elasticsearch cluster status is yellow.", + "message": "Allocate missing replica shards.", + "resolved_timestamp": "2017-08-23T21:45:31.882Z", + "timestamp": "2017-08-23T21:28:25.639Z" + } + ], + "isPrimary": true, + "status": "green" } ] diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail.json new file mode 100644 index 00000000000000..14c68ee4be07c9 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail.json @@ -0,0 +1,1245 @@ +{ + "indexSummary": { + "documents": 628, + "dataSize": { + "primaries": 4601000, + "total": 9202023 + }, + "unassignedShards": 0, + "totalShards": 10, + "status": "green" + }, + "metrics": { + "index_search_request_rate": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.search.query_total", + "metricAgg": "max", + "label": "Total Shards", + "title": "Search Rate", + "description": "Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + } + ], + "index_request_rate": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.indexing.index_total", + "metricAgg": "max", + "label": "Total Shards", + "title": "Indexing Rate", + "description": "Number of documents being indexed for primary and replica shards.", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.indexing.index_total", + "metricAgg": "max", + "label": "Primary Shards", + "title": "Indexing Rate", + "description": "Number of documents being indexed for primary shards.", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + } + ], + "index_size": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.store.size_in_bytes", + "metricAgg": "max", + "label": "Store", + "title": "Disk", + "description": "Size of primary and replica shards on disk.", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 9202023 + ], + [ + 1507235530000, + 9202023 + ], + [ + 1507235540000, + 9202023 + ], + [ + 1507235550000, + 9202023 + ], + [ + 1507235560000, + 9202023 + ], + [ + 1507235570000, + 9202023 + ], + [ + 1507235580000, + 9202023 + ], + [ + 1507235590000, + 9202023 + ], + [ + 1507235600000, + 9202023 + ], + [ + 1507235610000, + 9202023 + ], + [ + 1507235620000, + 9202023 + ], + [ + 1507235630000, + 9202023 + ], + [ + 1507235640000, + 9202023 + ], + [ + 1507235650000, + 9202023 + ], + [ + 1507235660000, + 9202023 + ], + [ + 1507235670000, + 9202023 + ], + [ + 1507235680000, + 9202023 + ], + [ + 1507235690000, + 9202023 + ], + [ + 1507235700000, + 9202023 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.store.size_in_bytes", + "metricAgg": "max", + "label": "Store (Primaries)", + "title": "Disk", + "description": "Size of primary shards on disk.", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 4601000 + ], + [ + 1507235530000, + 4601000 + ], + [ + 1507235540000, + 4601000 + ], + [ + 1507235550000, + 4601000 + ], + [ + 1507235560000, + 4601000 + ], + [ + 1507235570000, + 4601000 + ], + [ + 1507235580000, + 4601000 + ], + [ + 1507235590000, + 4601000 + ], + [ + 1507235600000, + 4601000 + ], + [ + 1507235610000, + 4601000 + ], + [ + 1507235620000, + 4601000 + ], + [ + 1507235630000, + 4601000 + ], + [ + 1507235640000, + 4601000 + ], + [ + 1507235650000, + 4601000 + ], + [ + 1507235660000, + 4601000 + ], + [ + 1507235670000, + 4601000 + ], + [ + 1507235680000, + 4601000 + ], + [ + 1507235690000, + 4601000 + ], + [ + 1507235700000, + 4601000 + ] + ] + } + ], + "index_mem": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.memory_in_bytes", + "metricAgg": "max", + "label": "Lucene Total", + "title": "Index Memory", + "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 2378656 + ], + [ + 1507235530000, + 2378656 + ], + [ + 1507235540000, + 2378656 + ], + [ + 1507235550000, + 2378656 + ], + [ + 1507235560000, + 2378656 + ], + [ + 1507235570000, + 2378656 + ], + [ + 1507235580000, + 2378656 + ], + [ + 1507235590000, + 2378656 + ], + [ + 1507235600000, + 2378656 + ], + [ + 1507235610000, + 2378656 + ], + [ + 1507235620000, + 2378656 + ], + [ + 1507235630000, + 2378656 + ], + [ + 1507235640000, + 2378656 + ], + [ + 1507235650000, + 2378656 + ], + [ + 1507235660000, + 2378656 + ], + [ + 1507235670000, + 2378656 + ], + [ + 1507235680000, + 2378656 + ], + [ + 1507235690000, + 2378656 + ], + [ + 1507235700000, + 2378656 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.terms_memory_in_bytes", + "metricAgg": "max", + "label": "Terms", + "title": "Index Memory", + "description": "Heap memory used by Terms (e.g., text). This is a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 1889180 + ], + [ + 1507235530000, + 1889180 + ], + [ + 1507235540000, + 1889180 + ], + [ + 1507235550000, + 1889180 + ], + [ + 1507235560000, + 1889180 + ], + [ + 1507235570000, + 1889180 + ], + [ + 1507235580000, + 1889180 + ], + [ + 1507235590000, + 1889180 + ], + [ + 1507235600000, + 1889180 + ], + [ + 1507235610000, + 1889180 + ], + [ + 1507235620000, + 1889180 + ], + [ + 1507235630000, + 1889180 + ], + [ + 1507235640000, + 1889180 + ], + [ + 1507235650000, + 1889180 + ], + [ + 1507235660000, + 1889180 + ], + [ + 1507235670000, + 1889180 + ], + [ + 1507235680000, + 1889180 + ], + [ + 1507235690000, + 1889180 + ], + [ + 1507235700000, + 1889180 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.points_memory_in_bytes", + "metricAgg": "max", + "label": "Points", + "title": "Index Memory", + "description": "Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 4644 + ], + [ + 1507235530000, + 4644 + ], + [ + 1507235540000, + 4644 + ], + [ + 1507235550000, + 4644 + ], + [ + 1507235560000, + 4644 + ], + [ + 1507235570000, + 4644 + ], + [ + 1507235580000, + 4644 + ], + [ + 1507235590000, + 4644 + ], + [ + 1507235600000, + 4644 + ], + [ + 1507235610000, + 4644 + ], + [ + 1507235620000, + 4644 + ], + [ + 1507235630000, + 4644 + ], + [ + 1507235640000, + 4644 + ], + [ + 1507235650000, + 4644 + ], + [ + 1507235660000, + 4644 + ], + [ + 1507235670000, + 4644 + ], + [ + 1507235680000, + 4644 + ], + [ + 1507235690000, + 4644 + ], + [ + 1507235700000, + 4644 + ] + ] + } + ], + "index_document_count": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.docs.count", + "metricAgg": "max", + "label": "Document Count", + "description": "Total number of documents, only including primary shards.", + "units": "", + "format": "0,0.[0]a", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 628 + ], + [ + 1507235530000, + 628 + ], + [ + 1507235540000, + 628 + ], + [ + 1507235550000, + 628 + ], + [ + 1507235560000, + 628 + ], + [ + 1507235570000, + 628 + ], + [ + 1507235580000, + 628 + ], + [ + 1507235590000, + 628 + ], + [ + 1507235600000, + 628 + ], + [ + 1507235610000, + 628 + ], + [ + 1507235620000, + 628 + ], + [ + 1507235630000, + 628 + ], + [ + 1507235640000, + 628 + ], + [ + 1507235650000, + 628 + ], + [ + 1507235660000, + 628 + ], + [ + 1507235670000, + 628 + ], + [ + 1507235680000, + 628 + ], + [ + 1507235690000, + 628 + ], + [ + 1507235700000, + 628 + ] + ] + } + ], + "index_segment_count": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.segments.count", + "metricAgg": "max", + "label": "Primaries", + "title": "Segment Count", + "description": "Number of segments for primary shards.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 30 + ], + [ + 1507235530000, + 30 + ], + [ + 1507235540000, + 30 + ], + [ + 1507235550000, + 30 + ], + [ + 1507235560000, + 30 + ], + [ + 1507235570000, + 30 + ], + [ + 1507235580000, + 30 + ], + [ + 1507235590000, + 30 + ], + [ + 1507235600000, + 30 + ], + [ + 1507235610000, + 30 + ], + [ + 1507235620000, + 30 + ], + [ + 1507235630000, + 30 + ], + [ + 1507235640000, + 30 + ], + [ + 1507235650000, + 30 + ], + [ + 1507235660000, + 30 + ], + [ + 1507235670000, + 30 + ], + [ + 1507235680000, + 30 + ], + [ + 1507235690000, + 30 + ], + [ + 1507235700000, + 30 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.count", + "metricAgg": "max", + "label": "Total", + "title": "Segment Count", + "description": "Number of segments for primary and replica shards.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 60 + ], + [ + 1507235530000, + 60 + ], + [ + 1507235540000, + 60 + ], + [ + 1507235550000, + 60 + ], + [ + 1507235560000, + 60 + ], + [ + 1507235570000, + 60 + ], + [ + 1507235580000, + 60 + ], + [ + 1507235590000, + 60 + ], + [ + 1507235600000, + 60 + ], + [ + 1507235610000, + 60 + ], + [ + 1507235620000, + 60 + ], + [ + 1507235630000, + 60 + ], + [ + 1507235640000, + 60 + ], + [ + 1507235650000, + 60 + ], + [ + 1507235660000, + 60 + ], + [ + 1507235670000, + 60 + ], + [ + 1507235680000, + 60 + ], + [ + 1507235690000, + 60 + ], + [ + 1507235700000, + 60 + ] + ] + } + ] + }, + "shards": [ + { + "state": "STARTED", + "primary": false, + "node": "xcP6ue7eRCieNNitFTT0EA", + "relocating_node": null, + "shard": 4, + "index": "avocado-tweets-2017.10.02", + "resolver": "xcP6ue7eRCieNNitFTT0EA" + }, + { + "state": "STARTED", + "primary": true, + "node": "jUT5KdxfRbORSCWkb5zjmA", + "relocating_node": null, + "shard": 4, + "index": "avocado-tweets-2017.10.02", + "resolver": "jUT5KdxfRbORSCWkb5zjmA" + }, + { + "state": "STARTED", + "primary": true, + "node": "xcP6ue7eRCieNNitFTT0EA", + "relocating_node": null, + "shard": 1, + "index": "avocado-tweets-2017.10.02", + "resolver": "xcP6ue7eRCieNNitFTT0EA" + }, + { + "state": "STARTED", + "primary": false, + "node": "jUT5KdxfRbORSCWkb5zjmA", + "relocating_node": null, + "shard": 1, + "index": "avocado-tweets-2017.10.02", + "resolver": "jUT5KdxfRbORSCWkb5zjmA" + }, + { + "state": "STARTED", + "primary": true, + "node": "xcP6ue7eRCieNNitFTT0EA", + "relocating_node": null, + "shard": 2, + "index": "avocado-tweets-2017.10.02", + "resolver": "xcP6ue7eRCieNNitFTT0EA" + }, + { + "state": "STARTED", + "primary": false, + "node": "jUT5KdxfRbORSCWkb5zjmA", + "relocating_node": null, + "shard": 2, + "index": "avocado-tweets-2017.10.02", + "resolver": "jUT5KdxfRbORSCWkb5zjmA" + }, + { + "state": "STARTED", + "primary": false, + "node": "xcP6ue7eRCieNNitFTT0EA", + "relocating_node": null, + "shard": 3, + "index": "avocado-tweets-2017.10.02", + "resolver": "xcP6ue7eRCieNNitFTT0EA" + }, + { + "state": "STARTED", + "primary": true, + "node": "jUT5KdxfRbORSCWkb5zjmA", + "relocating_node": null, + "shard": 3, + "index": "avocado-tweets-2017.10.02", + "resolver": "jUT5KdxfRbORSCWkb5zjmA" + }, + { + "state": "STARTED", + "primary": false, + "node": "xcP6ue7eRCieNNitFTT0EA", + "relocating_node": null, + "shard": 0, + "index": "avocado-tweets-2017.10.02", + "resolver": "xcP6ue7eRCieNNitFTT0EA" + }, + { + "state": "STARTED", + "primary": true, + "node": "jUT5KdxfRbORSCWkb5zjmA", + "relocating_node": null, + "shard": 0, + "index": "avocado-tweets-2017.10.02", + "resolver": "jUT5KdxfRbORSCWkb5zjmA" + } + ], + "shardStats": { + "nodes": { + "jUT5KdxfRbORSCWkb5zjmA": { + "shardCount": 38, + "indexCount": 20, + "name": "whatever-01", + "node_ids": [ + "jUT5KdxfRbORSCWkb5zjmA" + ], + "type": "master" + }, + "xcP6ue7eRCieNNitFTT0EA": { + "shardCount": 36, + "indexCount": 19, + "name": "whatever-02", + "node_ids": [ + "xcP6ue7eRCieNNitFTT0EA" + ], + "type": "node" + }, + "bwQWH-7IQY-mFPpfoaoFXQ": { + "shardCount": 4, + "indexCount": 4, + "name": "whatever-03", + "node_ids": [ + "bwQWH-7IQY-mFPpfoaoFXQ" + ], + "type": "node" + } + } + }, + "nodes": { + "jUT5KdxfRbORSCWkb5zjmA": { + "shardCount": 38, + "indexCount": 20, + "name": "whatever-01", + "node_ids": [ + "jUT5KdxfRbORSCWkb5zjmA" + ], + "type": "master" + }, + "xcP6ue7eRCieNNitFTT0EA": { + "shardCount": 36, + "indexCount": 19, + "name": "whatever-02", + "node_ids": [ + "xcP6ue7eRCieNNitFTT0EA" + ], + "type": "node" + }, + "bwQWH-7IQY-mFPpfoaoFXQ": { + "shardCount": 4, + "indexCount": 4, + "name": "whatever-03", + "node_ids": [ + "bwQWH-7IQY-mFPpfoaoFXQ" + ], + "type": "node" + } + }, + "stateUuid": "6wwwErXyTfaa4uHBHG5Pbg" +} diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail_advanced.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail_advanced.json new file mode 100644 index 00000000000000..ea5bede0db9771 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail_advanced.json @@ -0,0 +1,2944 @@ +{ + "indexSummary": { + "documents": 628, + "dataSize": { + "primaries": 4601000, + "total": 9202023 + }, + "unassignedShards": 0, + "totalShards": 10, + "status": "green" + }, + "metrics": { + "index_1": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.memory_in_bytes", + "metricAgg": "max", + "label": "Lucene Total", + "title": "Index Memory - Lucene 1", + "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 2378656 + ], + [ + 1507235530000, + 2378656 + ], + [ + 1507235540000, + 2378656 + ], + [ + 1507235550000, + 2378656 + ], + [ + 1507235560000, + 2378656 + ], + [ + 1507235570000, + 2378656 + ], + [ + 1507235580000, + 2378656 + ], + [ + 1507235590000, + 2378656 + ], + [ + 1507235600000, + 2378656 + ], + [ + 1507235610000, + 2378656 + ], + [ + 1507235620000, + 2378656 + ], + [ + 1507235630000, + 2378656 + ], + [ + 1507235640000, + 2378656 + ], + [ + 1507235650000, + 2378656 + ], + [ + 1507235660000, + 2378656 + ], + [ + 1507235670000, + 2378656 + ], + [ + 1507235680000, + 2378656 + ], + [ + 1507235690000, + 2378656 + ], + [ + 1507235700000, + 2378656 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.stored_fields_memory_in_bytes", + "metricAgg": "max", + "label": "Stored Fields", + "title": "Index Memory", + "description": "Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 19024 + ], + [ + 1507235530000, + 19024 + ], + [ + 1507235540000, + 19024 + ], + [ + 1507235550000, + 19024 + ], + [ + 1507235560000, + 19024 + ], + [ + 1507235570000, + 19024 + ], + [ + 1507235580000, + 19024 + ], + [ + 1507235590000, + 19024 + ], + [ + 1507235600000, + 19024 + ], + [ + 1507235610000, + 19024 + ], + [ + 1507235620000, + 19024 + ], + [ + 1507235630000, + 19024 + ], + [ + 1507235640000, + 19024 + ], + [ + 1507235650000, + 19024 + ], + [ + 1507235660000, + 19024 + ], + [ + 1507235670000, + 19024 + ], + [ + 1507235680000, + 19024 + ], + [ + 1507235690000, + 19024 + ], + [ + 1507235700000, + 19024 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.doc_values_memory_in_bytes", + "metricAgg": "max", + "label": "Doc Values", + "title": "Index Memory", + "description": "Heap memory used by Doc Values. This is a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 232336 + ], + [ + 1507235530000, + 232336 + ], + [ + 1507235540000, + 232336 + ], + [ + 1507235550000, + 232336 + ], + [ + 1507235560000, + 232336 + ], + [ + 1507235570000, + 232336 + ], + [ + 1507235580000, + 232336 + ], + [ + 1507235590000, + 232336 + ], + [ + 1507235600000, + 232336 + ], + [ + 1507235610000, + 232336 + ], + [ + 1507235620000, + 232336 + ], + [ + 1507235630000, + 232336 + ], + [ + 1507235640000, + 232336 + ], + [ + 1507235650000, + 232336 + ], + [ + 1507235660000, + 232336 + ], + [ + 1507235670000, + 232336 + ], + [ + 1507235680000, + 232336 + ], + [ + 1507235690000, + 232336 + ], + [ + 1507235700000, + 232336 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.norms_memory_in_bytes", + "metricAgg": "max", + "label": "Norms", + "title": "Index Memory", + "description": "Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 233472 + ], + [ + 1507235530000, + 233472 + ], + [ + 1507235540000, + 233472 + ], + [ + 1507235550000, + 233472 + ], + [ + 1507235560000, + 233472 + ], + [ + 1507235570000, + 233472 + ], + [ + 1507235580000, + 233472 + ], + [ + 1507235590000, + 233472 + ], + [ + 1507235600000, + 233472 + ], + [ + 1507235610000, + 233472 + ], + [ + 1507235620000, + 233472 + ], + [ + 1507235630000, + 233472 + ], + [ + 1507235640000, + 233472 + ], + [ + 1507235650000, + 233472 + ], + [ + 1507235660000, + 233472 + ], + [ + 1507235670000, + 233472 + ], + [ + 1507235680000, + 233472 + ], + [ + 1507235690000, + 233472 + ], + [ + 1507235700000, + 233472 + ] + ] + } + ], + "index_2": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.memory_in_bytes", + "metricAgg": "max", + "label": "Lucene Total", + "title": "Index Memory - Lucene 2", + "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 2378656 + ], + [ + 1507235530000, + 2378656 + ], + [ + 1507235540000, + 2378656 + ], + [ + 1507235550000, + 2378656 + ], + [ + 1507235560000, + 2378656 + ], + [ + 1507235570000, + 2378656 + ], + [ + 1507235580000, + 2378656 + ], + [ + 1507235590000, + 2378656 + ], + [ + 1507235600000, + 2378656 + ], + [ + 1507235610000, + 2378656 + ], + [ + 1507235620000, + 2378656 + ], + [ + 1507235630000, + 2378656 + ], + [ + 1507235640000, + 2378656 + ], + [ + 1507235650000, + 2378656 + ], + [ + 1507235660000, + 2378656 + ], + [ + 1507235670000, + 2378656 + ], + [ + 1507235680000, + 2378656 + ], + [ + 1507235690000, + 2378656 + ], + [ + 1507235700000, + 2378656 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.terms_memory_in_bytes", + "metricAgg": "max", + "label": "Terms", + "title": "Index Memory", + "description": "Heap memory used by Terms (e.g., text). This is a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 1889180 + ], + [ + 1507235530000, + 1889180 + ], + [ + 1507235540000, + 1889180 + ], + [ + 1507235550000, + 1889180 + ], + [ + 1507235560000, + 1889180 + ], + [ + 1507235570000, + 1889180 + ], + [ + 1507235580000, + 1889180 + ], + [ + 1507235590000, + 1889180 + ], + [ + 1507235600000, + 1889180 + ], + [ + 1507235610000, + 1889180 + ], + [ + 1507235620000, + 1889180 + ], + [ + 1507235630000, + 1889180 + ], + [ + 1507235640000, + 1889180 + ], + [ + 1507235650000, + 1889180 + ], + [ + 1507235660000, + 1889180 + ], + [ + 1507235670000, + 1889180 + ], + [ + 1507235680000, + 1889180 + ], + [ + 1507235690000, + 1889180 + ], + [ + 1507235700000, + 1889180 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.points_memory_in_bytes", + "metricAgg": "max", + "label": "Points", + "title": "Index Memory", + "description": "Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 4644 + ], + [ + 1507235530000, + 4644 + ], + [ + 1507235540000, + 4644 + ], + [ + 1507235550000, + 4644 + ], + [ + 1507235560000, + 4644 + ], + [ + 1507235570000, + 4644 + ], + [ + 1507235580000, + 4644 + ], + [ + 1507235590000, + 4644 + ], + [ + 1507235600000, + 4644 + ], + [ + 1507235610000, + 4644 + ], + [ + 1507235620000, + 4644 + ], + [ + 1507235630000, + 4644 + ], + [ + 1507235640000, + 4644 + ], + [ + 1507235650000, + 4644 + ], + [ + 1507235660000, + 4644 + ], + [ + 1507235670000, + 4644 + ], + [ + 1507235680000, + 4644 + ], + [ + 1507235690000, + 4644 + ], + [ + 1507235700000, + 4644 + ] + ] + } + ], + "index_3": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.memory_in_bytes", + "metricAgg": "max", + "label": "Lucene Total", + "title": "Index Memory - Lucene 3", + "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 2378656 + ], + [ + 1507235530000, + 2378656 + ], + [ + 1507235540000, + 2378656 + ], + [ + 1507235550000, + 2378656 + ], + [ + 1507235560000, + 2378656 + ], + [ + 1507235570000, + 2378656 + ], + [ + 1507235580000, + 2378656 + ], + [ + 1507235590000, + 2378656 + ], + [ + 1507235600000, + 2378656 + ], + [ + 1507235610000, + 2378656 + ], + [ + 1507235620000, + 2378656 + ], + [ + 1507235630000, + 2378656 + ], + [ + 1507235640000, + 2378656 + ], + [ + 1507235650000, + 2378656 + ], + [ + 1507235660000, + 2378656 + ], + [ + 1507235670000, + 2378656 + ], + [ + 1507235680000, + 2378656 + ], + [ + 1507235690000, + 2378656 + ], + [ + 1507235700000, + 2378656 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.fixed_bit_set_memory_in_bytes", + "metricAgg": "max", + "label": "Fixed Bitsets", + "title": "Index Memory", + "description": "Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 0 + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.term_vectors_memory_in_bytes", + "metricAgg": "max", + "label": "Term Vectors", + "title": "Index Memory", + "description": "Heap memory used by Term Vectors. This is a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 0 + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.version_map_memory_in_bytes", + "metricAgg": "max", + "label": "Version Map", + "title": "Index Memory", + "description": "Heap memory used by Versioning (e.g., updates and deletes). This is NOT a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 0 + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + } + ], + "index_4": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.query_cache.memory_size_in_bytes", + "metricAgg": "max", + "label": "Query Cache", + "title": "Index Memory - Elasticsearch", + "description": "Heap memory used by Query Cache (e.g., cached filters). This is for the same shards, but not a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 0 + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.request_cache.memory_size_in_bytes", + "metricAgg": "max", + "label": "Request Cache", + "title": "Index Memory", + "description": "Heap memory used by Request Cache (e.g., instant aggregations). This is for the same shards, but not a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 0 + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.fielddata.memory_size_in_bytes", + "metricAgg": "max", + "label": "Fielddata", + "title": "Index Memory", + "description": "Heap memory used by Fielddata (e.g., global ordinals or explicitly enabled fielddata on text fields). This is for the same shards, but not a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 0 + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.index_writer_memory_in_bytes", + "metricAgg": "max", + "label": "Index Writer", + "title": "Index Memory", + "description": "Heap memory used by the Index Writer. This is NOT a part of Lucene Total.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 0 + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + } + ], + "index_total": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.search.query_total", + "metricAgg": "max", + "label": "Search Total", + "title": "Request Rate", + "description": "Amount of search operations (per shard).", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.indexing.index_total", + "metricAgg": "max", + "label": "Index Total", + "title": "Request Rate", + "description": "Amount of indexing operations.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + } + ], + "index_time": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.search.query_time_in_millis", + "metricAgg": "max", + "label": "Search", + "title": "Request Time", + "description": "Amount of time spent performing search operations (per shard).", + "units": "ms", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.indexing.index_time_in_millis", + "metricAgg": "max", + "label": "Indexing", + "title": "Request Time", + "description": "Amount of time spent performing index operations on primary and replica shards.", + "units": "ms", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.indexing.index_time_in_millis", + "metricAgg": "max", + "label": "Indexing (Primaries)", + "title": "Request Time", + "description": "Amount of time spent performing index operations on primary shards only.", + "units": "ms", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + } + ], + "index_throttling": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.indexing.throttle_time_in_millis", + "metricAgg": "max", + "label": "Indexing", + "title": "Throttle Time", + "description": "Amount of time spent throttling index operations on primary and replica shards.", + "units": "ms", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.indexing.throttle_time_in_millis", + "metricAgg": "max", + "label": "Indexing (Primaries)", + "title": "Throttle Time", + "description": "Amount of time spent throttling index operations on primary shards.", + "units": "ms", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + } + ], + "index_refresh": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.refresh.total_time_in_millis", + "metricAgg": "max", + "label": "Total", + "title": "Refresh Time", + "description": "Amount of time spent to perform refresh operations on primary and replica shards.", + "units": "ms", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.refresh.total_time_in_millis", + "metricAgg": "max", + "label": "Primaries", + "title": "Refresh Time", + "description": "Amount of time spent to perform refresh operations on primary shards.", + "units": "ms", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + } + ], + "index_disk": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.store.size_in_bytes", + "metricAgg": "max", + "label": "Store", + "title": "Disk", + "description": "Size of primary and replica shards on disk.", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 9202023 + ], + [ + 1507235530000, + 9202023 + ], + [ + 1507235540000, + 9202023 + ], + [ + 1507235550000, + 9202023 + ], + [ + 1507235560000, + 9202023 + ], + [ + 1507235570000, + 9202023 + ], + [ + 1507235580000, + 9202023 + ], + [ + 1507235590000, + 9202023 + ], + [ + 1507235600000, + 9202023 + ], + [ + 1507235610000, + 9202023 + ], + [ + 1507235620000, + 9202023 + ], + [ + 1507235630000, + 9202023 + ], + [ + 1507235640000, + 9202023 + ], + [ + 1507235650000, + 9202023 + ], + [ + 1507235660000, + 9202023 + ], + [ + 1507235670000, + 9202023 + ], + [ + 1507235680000, + 9202023 + ], + [ + 1507235690000, + 9202023 + ], + [ + 1507235700000, + 9202023 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.store.size_in_bytes", + "metricAgg": "max", + "label": "Store (Primaries)", + "title": "Disk", + "description": "Size of primary shards on disk.", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 4601000 + ], + [ + 1507235530000, + 4601000 + ], + [ + 1507235540000, + 4601000 + ], + [ + 1507235550000, + 4601000 + ], + [ + 1507235560000, + 4601000 + ], + [ + 1507235570000, + 4601000 + ], + [ + 1507235580000, + 4601000 + ], + [ + 1507235590000, + 4601000 + ], + [ + 1507235600000, + 4601000 + ], + [ + 1507235610000, + 4601000 + ], + [ + 1507235620000, + 4601000 + ], + [ + 1507235630000, + 4601000 + ], + [ + 1507235640000, + 4601000 + ], + [ + 1507235650000, + 4601000 + ], + [ + 1507235660000, + 4601000 + ], + [ + 1507235670000, + 4601000 + ], + [ + 1507235680000, + 4601000 + ], + [ + 1507235690000, + 4601000 + ], + [ + 1507235700000, + 4601000 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.merges.total_size_in_bytes", + "metricAgg": "max", + "label": "Merges", + "title": "Disk", + "description": "Size of merges on primary and replica shards.", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.merges.total_size_in_bytes", + "metricAgg": "max", + "label": "Merges (Primaries)", + "title": "Disk", + "description": "Size of merges on primary shards.", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1507235520000, + null + ], + [ + 1507235530000, + 0 + ], + [ + 1507235540000, + 0 + ], + [ + 1507235550000, + 0 + ], + [ + 1507235560000, + 0 + ], + [ + 1507235570000, + 0 + ], + [ + 1507235580000, + 0 + ], + [ + 1507235590000, + 0 + ], + [ + 1507235600000, + 0 + ], + [ + 1507235610000, + 0 + ], + [ + 1507235620000, + 0 + ], + [ + 1507235630000, + 0 + ], + [ + 1507235640000, + 0 + ], + [ + 1507235650000, + 0 + ], + [ + 1507235660000, + 0 + ], + [ + 1507235670000, + 0 + ], + [ + 1507235680000, + 0 + ], + [ + 1507235690000, + 0 + ], + [ + 1507235700000, + 0 + ] + ] + } + ], + "index_segment_count": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.total.segments.count", + "metricAgg": "max", + "label": "Total", + "title": "Segment Count", + "description": "Number of segments for primary and replica shards.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 60 + ], + [ + 1507235530000, + 60 + ], + [ + 1507235540000, + 60 + ], + [ + 1507235550000, + 60 + ], + [ + 1507235560000, + 60 + ], + [ + 1507235570000, + 60 + ], + [ + 1507235580000, + 60 + ], + [ + 1507235590000, + 60 + ], + [ + 1507235600000, + 60 + ], + [ + 1507235610000, + 60 + ], + [ + 1507235620000, + 60 + ], + [ + 1507235630000, + 60 + ], + [ + 1507235640000, + 60 + ], + [ + 1507235650000, + 60 + ], + [ + 1507235660000, + 60 + ], + [ + 1507235670000, + 60 + ], + [ + 1507235680000, + 60 + ], + [ + 1507235690000, + 60 + ], + [ + 1507235700000, + 60 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1507235508000, + "max": 1507235712000 + }, + "metric": { + "app": "elasticsearch", + "field": "index_stats.primaries.segments.count", + "metricAgg": "max", + "label": "Primaries", + "title": "Segment Count", + "description": "Number of segments for primary shards.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1507235520000, + 30 + ], + [ + 1507235530000, + 30 + ], + [ + 1507235540000, + 30 + ], + [ + 1507235550000, + 30 + ], + [ + 1507235560000, + 30 + ], + [ + 1507235570000, + 30 + ], + [ + 1507235580000, + 30 + ], + [ + 1507235590000, + 30 + ], + [ + 1507235600000, + 30 + ], + [ + 1507235610000, + 30 + ], + [ + 1507235620000, + 30 + ], + [ + 1507235630000, + 30 + ], + [ + 1507235640000, + 30 + ], + [ + 1507235650000, + 30 + ], + [ + 1507235660000, + 30 + ], + [ + 1507235670000, + 30 + ], + [ + 1507235680000, + 30 + ], + [ + 1507235690000, + 30 + ], + [ + 1507235700000, + 30 + ] + ] + } + ] + } +} diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_red_cluster.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_red_cluster.json new file mode 100644 index 00000000000000..eee164d10b65f0 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_red_cluster.json @@ -0,0 +1,274 @@ +{ + "clusterStatus": { + "status": "red", + "indicesCount": 19, + "documentCount": 4535, + "dataSize": 9036305, + "nodesCount": 1, + "upTime": 1403187, + "version": [ + "7.0.0-alpha1" + ], + "memUsed": 280753264, + "memMax": 709623808, + "unassignedShards": 23, + "totalShards": 46 + }, + "indices": [ + { + "name": "many-0010_dgnlpqtstfvi", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0024_rixhhwzyiczb", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0016_gyvtsyauoqqg", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0006_gkuqbjonkjmg", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 4.0788690476190474, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0022_dqbcjopzejlk", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0020_fqfovcnznbus", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0012_jwomwdgfpisl", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0018_ipugjcmuagih", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0008_amnscruqlsnu", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 4.0788690476190474, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0014_zrukbrvuluby", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "phone-home", + "status": "yellow", + "doc_count": 1, + "data_size": 67798, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 5, + "status_sort": 2 + }, + { + "name": "many-0015_vwmrucgzvohb", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0009_reolfgzjjtvh", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0011_xtkcmlwmxcov", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0019_slpgftmneikv", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0017_zpyxggzmytun", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0025_xmvpnfeuqxtp", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0013_smjuwdkhpduv", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0007_milycdknpycp", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0021_xjtlceanhvup", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0.000744047619047619, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0023_hkbvktonytxh", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0005_dnzzblxoumfe", + "status": "Deleted / Closed", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "status_sort": 0 + }, + { + "name": "many-0004_wzgjkelqclur", + "status": "Deleted / Closed", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "status_sort": 0 + }, + { + "name": "many-0002_emdkmgdeflno", + "status": "Deleted / Closed", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "status_sort": 0 + }, + { + "name": "many-0003_jbwrztjwhkjt", + "status": "Deleted / Closed", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "status_sort": 0 + }, + { + "name": "many-0001_clruksahirti", + "status": "Deleted / Closed", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "status_sort": 0 + } + ] +} diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_red_cluster_all.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_red_cluster_all.json new file mode 100644 index 00000000000000..01917231808801 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_red_cluster_all.json @@ -0,0 +1,354 @@ +{ + "clusterStatus": { + "status": "red", + "indicesCount": 19, + "documentCount": 4535, + "dataSize": 9036305, + "nodesCount": 1, + "upTime": 1403187, + "version": [ + "7.0.0-alpha1" + ], + "memUsed": 280753264, + "memMax": 709623808, + "unassignedShards": 23, + "totalShards": 46 + }, + "indices": [ + { + "name": ".triggered_watches", + "status": "yellow", + "doc_count": 0, + "data_size": 134430, + "index_rate": 0.078125, + "search_rate": 0.001488095238095238, + "unassigned_shards": 1, + "status_sort": 2 + }, + { + "name": "many-0010_dgnlpqtstfvi", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0024_rixhhwzyiczb", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": ".watcher-history-7-2017.10.05", + "status": "yellow", + "doc_count": 404, + "data_size": 707598, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 2 + }, + { + "name": "many-0016_gyvtsyauoqqg", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": ".watcher-history-7-2017.10.06", + "status": "yellow", + "doc_count": 1978, + "data_size": 5256199, + "index_rate": 0.078125, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 2 + }, + { + "name": "many-0006_gkuqbjonkjmg", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 4.0788690476190474, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": ".monitoring-es-6-2017.10.06", + "status": "yellow", + "doc_count": 2001, + "data_size": 2607666, + "index_rate": 2.2202380952380953, + "search_rate": 2.34375, + "unassigned_shards": 1, + "status_sort": 2 + }, + { + "name": "many-0022_dqbcjopzejlk", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0020_fqfovcnznbus", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0012_jwomwdgfpisl", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": ".monitoring-kibana-6-2017.10.06", + "status": "yellow", + "doc_count": 134, + "data_size": 171216, + "index_rate": 0.09672619047619048, + "search_rate": 0.09672619047619048, + "unassigned_shards": 1, + "status_sort": 2 + }, + { + "name": "many-0018_ipugjcmuagih", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0008_amnscruqlsnu", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 4.0788690476190474, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": "many-0014_zrukbrvuluby", + "status": "green", + "doc_count": 1, + "data_size": 3821, + "index_rate": 0, + "search_rate": 1.9449404761904763, + "unassigned_shards": 0, + "status_sort": 1 + }, + { + "name": ".kibana", + "status": "yellow", + "doc_count": 1, + "data_size": 5406, + "index_rate": 0, + "search_rate": 0.34672619047619047, + "unassigned_shards": 1, + "status_sort": 2 + }, + { + "name": ".monitoring-alerts-6", + "status": "yellow", + "doc_count": 1, + "data_size": 6706, + "index_rate": 0.012648809523809524, + "search_rate": 0.07738095238095238, + "unassigned_shards": 1, + "status_sort": 2 + }, + { + "name": "phone-home", + "status": "yellow", + "doc_count": 1, + "data_size": 67798, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 5, + "status_sort": 2 + }, + { + "name": ".watches", + "status": "yellow", + "doc_count": 5, + "data_size": 41076, + "index_rate": 0.078125, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 2 + }, + { + "name": "many-0015_vwmrucgzvohb", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0009_reolfgzjjtvh", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0011_xtkcmlwmxcov", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0019_slpgftmneikv", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0017_zpyxggzmytun", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0025_xmvpnfeuqxtp", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0013_smjuwdkhpduv", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0007_milycdknpycp", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0021_xjtlceanhvup", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0.000744047619047619, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0023_hkbvktonytxh", + "status": "red", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "unassigned_shards": 1, + "status_sort": 3 + }, + { + "name": "many-0005_dnzzblxoumfe", + "status": "Deleted / Closed", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "status_sort": 0 + }, + { + "name": "many-0004_wzgjkelqclur", + "status": "Deleted / Closed", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "status_sort": 0 + }, + { + "name": "many-0002_emdkmgdeflno", + "status": "Deleted / Closed", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "status_sort": 0 + }, + { + "name": "many-0003_jbwrztjwhkjt", + "status": "Deleted / Closed", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "status_sort": 0 + }, + { + "name": "many-0001_clruksahirti", + "status": "Deleted / Closed", + "doc_count": 1, + "data_size": 3728, + "index_rate": 0, + "search_rate": 0, + "status_sort": 0 + } + ] +} diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_shards_relocating.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_shards_relocating.json new file mode 100644 index 00000000000000..88660711b9c9cf --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_shards_relocating.json @@ -0,0 +1,79 @@ +{ + "clusterStatus": { + "status": "yellow", + "indicesCount": 20, + "documentCount": 25927, + "dataSize": 106492436, + "nodesCount": 3, + "upTime": 1187008, + "version": [ + "7.0.0-alpha1" + ], + "memUsed": 603241144, + "memMax": 2128871424, + "unassignedShards": 5, + "totalShards": 80 + }, + "indices": [ + { + "name": "watermelon-tweets-2017.10.05", + "doc_count": 3, + "data_size": 232955, + "index_rate": 0, + "search_rate": 0, + "status": "yellow", + "status_sort": 2, + "unassigned_shards": 1 + }, + { + "name": "avocado-tweets-2017.10.02", + "doc_count": 628, + "data_size": 9202023, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": "avocado-tweets-2017.10.03", + "doc_count": 1154, + "data_size": 14962115, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": "relocation_test", + "doc_count": 1, + "data_size": 4870, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": "avocado-tweets-2017.09.30", + "doc_count": 1991, + "data_size": 20947574, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": "phone-home", + "doc_count": 10, + "data_size": 1278604, + "index_rate": 0, + "search_rate": 0, + "status": "yellow", + "status_sort": 2, + "unassigned_shards": 1 + } + ] +} diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_shards_relocating_all.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_shards_relocating_all.json new file mode 100644 index 00000000000000..96b0802786f605 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/indices_shards_relocating_all.json @@ -0,0 +1,219 @@ +{ + "clusterStatus": { + "status": "yellow", + "indicesCount": 20, + "documentCount": 25927, + "dataSize": 106492436, + "nodesCount": 3, + "upTime": 1187008, + "version": [ + "7.0.0-alpha1" + ], + "memUsed": 603241144, + "memMax": 2128871424, + "unassignedShards": 5, + "totalShards": 80 + }, + "indices": [ + { + "name": ".triggered_watches", + "doc_count": 0, + "data_size": 28561, + "index_rate": 0.08823529411764706, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": "watermelon-tweets-2017.10.05", + "doc_count": 3, + "data_size": 232955, + "index_rate": 0, + "search_rate": 0, + "status": "yellow", + "status_sort": 2, + "unassigned_shards": 1 + }, + { + "name": "avocado-tweets-2017.10.02", + "doc_count": 628, + "data_size": 9202023, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": ".watcher-history-7-2017.09.29", + "doc_count": 1743, + "data_size": 4640398, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": "avocado-tweets-2017.10.03", + "doc_count": 1154, + "data_size": 14962115, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": ".watcher-history-7-2017.10.05", + "doc_count": 2304, + "data_size": 11481351, + "index_rate": 0.08823529411764706, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": ".watcher-history-7-2017.10.03", + "doc_count": 3242, + "data_size": 8986146, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": ".watcher-history-7-2017.10.04", + "doc_count": 3815, + "data_size": 9433688, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": ".watcher-history-7-2017.10.01", + "doc_count": 35, + "data_size": 486636, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": ".watcher-history-7-2017.10.02", + "doc_count": 3185, + "data_size": 8140314, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": ".monitoring-es-6-2017.10.05", + "doc_count": 1077, + "data_size": 516721, + "index_rate": 9.117647058823529, + "search_rate": 1.7352941176470589, + "status": "yellow", + "status_sort": 2, + "unassigned_shards": 1 + }, + { + "name": ".security-v6", + "doc_count": 7, + "data_size": 61276, + "index_rate": 0, + "search_rate": 0, + "status": "yellow", + "status_sort": 2, + "unassigned_shards": 1 + }, + { + "name": ".watcher-history-7-2017.09.30", + "doc_count": 6706, + "data_size": 15809068, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": ".kibana", + "doc_count": 2, + "data_size": 44821, + "index_rate": 0, + "search_rate": 0.7058823529411765, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": ".monitoring-alerts-6", + "doc_count": 1, + "data_size": 13650, + "index_rate": 0.00980392156862745, + "search_rate": 0.05392156862745098, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": "relocation_test", + "doc_count": 1, + "data_size": 4870, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": "avocado-tweets-2017.09.30", + "doc_count": 1991, + "data_size": 20947574, + "index_rate": 0, + "search_rate": 0, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": ".watches", + "doc_count": 5, + "data_size": 96351, + "index_rate": 0.08823529411764706, + "search_rate": 0.00980392156862745, + "status": "green", + "status_sort": 1, + "unassigned_shards": 0 + }, + { + "name": "phone-home", + "doc_count": 10, + "data_size": 1278604, + "index_rate": 0, + "search_rate": 0, + "status": "yellow", + "status_sort": 2, + "unassigned_shards": 1 + }, + { + "name": ".monitoring-kibana-6-2017.10.05", + "doc_count": 18, + "data_size": 125314, + "index_rate": 0.08333333333333333, + "search_rate": 0.11764705882352941, + "status": "yellow", + "status_sort": 2, + "unassigned_shards": 1 + } + ] +} diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail.json index 2fef16e6602f28..29d50d10dbd210 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail.json +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail.json @@ -990,6 +990,7 @@ "documents": 24830, "freeSpace": 186755088384, "indexCount": 20, + "isOnline": true, "name": "whatever-01", "nodeTypeClass": "fa-star", "nodeTypeLabel": "Master Node", diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/index.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/index.js index 582729b8905d73..a69144ecc5b047 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/index.js +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/index.js @@ -9,5 +9,7 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./overview')); loadTestFile(require.resolve('./nodes')); loadTestFile(require.resolve('./node_detail')); + loadTestFile(require.resolve('./indices')); + loadTestFile(require.resolve('./index_detail')); }); } diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/index_detail.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/index_detail.js new file mode 100644 index 00000000000000..b9af7be8154aa1 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/index_detail.js @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from 'expect.js'; +import indexDetailFixture from './fixtures/index_detail'; +import indexDetailAdvancedFixture from './fixtures/index_detail_advanced'; + +export default function ({ getService }) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('index detail', () => { + const archive = 'monitoring/singlecluster-three-nodes-shard-relocation'; + const timeRange = { + min: '2017-10-05T20:31:48.000Z', + max: '2017-10-05T20:35:12.000Z' + }; + + before('load archive', () => { + return esArchiver.load(archive); + }); + + after('unload archive', () => { + return esArchiver.unload(archive); + }); + + it('should summarize index with chart metrics data for the non-advanced view', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/YCxj-RAgSZCP6GuOQ8M1EQ/elasticsearch/indices/avocado-tweets-2017.10.02') + .set('kbn-xsrf', 'xxx') + .send({ + timeRange, + is_advanced: false + }) + .expect(200); + + expect(body).to.eql(indexDetailFixture); + }); + + it('should summarize index with chart metrics data for the advanced view', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/YCxj-RAgSZCP6GuOQ8M1EQ/elasticsearch/indices/avocado-tweets-2017.10.02') + .set('kbn-xsrf', 'xxx') + .send({ + timeRange, + is_advanced: true + }) + .expect(200); + + expect(body).to.eql(indexDetailAdvancedFixture); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/indices.js b/x-pack/test/api_integration/apis/monitoring/elasticsearch/indices.js new file mode 100644 index 00000000000000..9e4b072796590c --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/indices.js @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from 'expect.js'; +import relocatingShardsFixture from './fixtures/indices_shards_relocating'; +import relocationShardsAllFixture from './fixtures/indices_shards_relocating_all'; +import indicesRedClusterFixture from './fixtures/indices_red_cluster'; +import indicesRedClusterAllFixture from './fixtures/indices_red_cluster_all'; + +export default function ({ getService }) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('indices', () => { + describe('shard-relocation', () => { + const archive = 'monitoring/singlecluster-three-nodes-shard-relocation'; + const timeRange = { + min: '2017-10-05T20:31:48.000Z', + max: '2017-10-05T20:35:12.000Z' + }; + + before('load archive', () => { + return esArchiver.load(archive); + }); + + after('unload archive', () => { + return esArchiver.unload(archive); + }); + + it('should summarize the non-system indices with stats', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/YCxj-RAgSZCP6GuOQ8M1EQ/elasticsearch/indices?show_system_indices=false') + .set('kbn-xsrf', 'xxx') + .send({ timeRange }) + .expect(200); + + expect(body).to.eql(relocatingShardsFixture); + }); + + it('should summarize all indices with stats', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/YCxj-RAgSZCP6GuOQ8M1EQ/elasticsearch/indices?show_system_indices=true') + .set('kbn-xsrf', 'xxx') + .send({ timeRange }) + .expect(200); + + expect(body).to.eql(relocationShardsAllFixture); + }); + }); + + describe('health-red', () => { + const archive = 'monitoring/singlecluster-red-platinum'; + const timeRange = { + min: '2017-10-06T19:53:06.000Z', + max: '2017-10-06T20:15:30.000Z' + }; + + before('load clusters archive', () => { + return esArchiver.load(archive); + }); + + after('unload clusters archive', () => { + return esArchiver.unload(archive); + }); + + it('should summarize the non-system indices with stats', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/1LYuyvCCQFS3FAO_h65PQw/elasticsearch/indices?show_system_indices=false') + .set('kbn-xsrf', 'xxx') + .send({ timeRange }) + .expect(200); + expect(body).to.eql(indicesRedClusterFixture); + }); + + it('should summarize all indices with stats', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/1LYuyvCCQFS3FAO_h65PQw/elasticsearch/indices?show_system_indices=true') + .set('kbn-xsrf', 'xxx') + .send({ timeRange }) + .expect(200); + + expect(body).to.eql(indicesRedClusterAllFixture); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/monitoring/kibana/fixtures/instance.json b/x-pack/test/api_integration/apis/monitoring/kibana/fixtures/instance.json new file mode 100644 index 00000000000000..df3df7043e2c5c --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/kibana/fixtures/instance.json @@ -0,0 +1,596 @@ +{ + "metrics": { + "kibana_os_load": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1504027457000, + "max": 1504027568000 + }, + "metric": { + "app": "kibana", + "field": "kibana_stats.os.load.1m", + "metricAgg": "max", + "label": "1m", + "title": "System Load", + "description": "Load average over the last minute.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1504027460000, + 5.87109375 + ], + [ + 1504027470000, + 5.84375 + ], + [ + 1504027480000, + 5.08984375 + ], + [ + 1504027490000, + 4.53515625 + ], + [ + 1504027500000, + 3.990234375 + ], + [ + 1504027510000, + 3.537109375 + ], + [ + 1504027520000, + 3.29296875 + ], + [ + 1504027530000, + 3.2421875 + ], + [ + 1504027540000, + 3.19140625 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1504027457000, + "max": 1504027568000 + }, + "metric": { + "app": "kibana", + "field": "kibana_stats.os.load.5m", + "metricAgg": "max", + "label": "5m", + "title": "System Load", + "description": "Load average over the last 5 minutes.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1504027460000, + 4.92578125 + ], + [ + 1504027470000, + 4.9453125 + ], + [ + 1504027480000, + 4.81640625 + ], + [ + 1504027490000, + 4.70703125 + ], + [ + 1504027500000, + 4.58203125 + ], + [ + 1504027510000, + 4.46484375 + ], + [ + 1504027520000, + 4.3828125 + ], + [ + 1504027530000, + 4.3359375 + ], + [ + 1504027540000, + 4.29296875 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1504027457000, + "max": 1504027568000 + }, + "metric": { + "app": "kibana", + "field": "kibana_stats.os.load.15m", + "metricAgg": "max", + "label": "15m", + "title": "System Load", + "description": "Load average over the last 15 minutes.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1504027460000, + 4.5390625 + ], + [ + 1504027470000, + 4.546875 + ], + [ + 1504027480000, + 4.5078125 + ], + [ + 1504027490000, + 4.46875 + ], + [ + 1504027500000, + 4.4296875 + ], + [ + 1504027510000, + 4.390625 + ], + [ + 1504027520000, + 4.359375 + ], + [ + 1504027530000, + 4.34375 + ], + [ + 1504027540000, + 4.328125 + ] + ] + } + ], + "kibana_average_concurrent_connections": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1504027457000, + "max": 1504027568000 + }, + "metric": { + "app": "kibana", + "field": "kibana_stats.concurrent_connections", + "metricAgg": "max", + "label": "HTTP Connections", + "description": "Total number of open socket connections to the Kibana instance.", + "units": "", + "format": "0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1504027460000, + 78 + ], + [ + 1504027470000, + 90 + ], + [ + 1504027480000, + 102 + ], + [ + 1504027490000, + 114 + ], + [ + 1504027500000, + 126 + ], + [ + 1504027510000, + 138 + ], + [ + 1504027520000, + 150 + ], + [ + 1504027530000, + 162 + ], + [ + 1504027540000, + 174 + ] + ] + } + ], + "kibana_process_delay": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1504027457000, + "max": 1504027568000 + }, + "metric": { + "app": "kibana", + "field": "kibana_stats.process.event_loop_delay", + "metricAgg": "max", + "label": "Event Loop Delay", + "description": "Delay in Kibana server event loops. Longer delays may indicate blocking events in server thread, such as synchronous functions taking large amount of CPU time.", + "units": "ms", + "format": "0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1504027460000, + 9.576263427734375 + ], + [ + 1504027470000, + 10.395200729370117 + ], + [ + 1504027480000, + 11.072744369506836 + ], + [ + 1504027490000, + 11.617706298828125 + ], + [ + 1504027500000, + 12.510245323181152 + ], + [ + 1504027510000, + 13.343531608581543 + ], + [ + 1504027520000, + 14.059904098510742 + ], + [ + 1504027530000, + 14.816107749938965 + ], + [ + 1504027540000, + 15.663384437561035 + ] + ] + } + ], + "kibana_memory": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1504027457000, + "max": 1504027568000 + }, + "metric": { + "app": "kibana", + "field": "kibana_stats.process.memory.heap.size_limit", + "metricAgg": "max", + "label": "Heap Size Limit", + "title": "Memory Size", + "description": "Limit of memory usage before garbage collection.", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1504027460000, + 1501560832 + ], + [ + 1504027470000, + 1501560832 + ], + [ + 1504027480000, + 1501560832 + ], + [ + 1504027490000, + 1501560832 + ], + [ + 1504027500000, + 1501560832 + ], + [ + 1504027510000, + 1501560832 + ], + [ + 1504027520000, + 1501560832 + ], + [ + 1504027530000, + 1501560832 + ], + [ + 1504027540000, + 1501560832 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1504027457000, + "max": 1504027568000 + }, + "metric": { + "app": "kibana", + "field": "kibana_stats.process.memory.resident_set_size_in_bytes", + "metricAgg": "max", + "label": "Memory Size", + "title": "Memory Size", + "description": "Total heap used by Kibana running in Node.js.", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1504027460000, + 228552704 + ], + [ + 1504027470000, + 231333888 + ], + [ + 1504027480000, + 232230912 + ], + [ + 1504027490000, + 229707776 + ], + [ + 1504027500000, + 230150144 + ], + [ + 1504027510000, + 230617088 + ], + [ + 1504027520000, + 229924864 + ], + [ + 1504027530000, + 230363136 + ], + [ + 1504027540000, + 230227968 + ] + ] + } + ], + "kibana_response_times": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1504027457000, + "max": 1504027568000 + }, + "metric": { + "app": "kibana", + "field": "kibana_stats.response_times.max", + "metricAgg": "max", + "label": "Max", + "title": "Client Response Time", + "description": "Maximum response time for client requests to the Kibana instance.", + "units": "ms", + "format": "0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1504027460000, + 2203 + ], + [ + 1504027470000, + 2203 + ], + [ + 1504027480000, + 2203 + ], + [ + 1504027490000, + 2203 + ], + [ + 1504027500000, + 2203 + ], + [ + 1504027510000, + 2203 + ], + [ + 1504027520000, + 2203 + ], + [ + 1504027530000, + 2203 + ], + [ + 1504027540000, + 2203 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1504027457000, + "max": 1504027568000 + }, + "metric": { + "app": "kibana", + "field": "kibana_stats.response_times.average", + "metricAgg": "max", + "label": "Average", + "title": "Client Response Time", + "description": "Average response time for client requests to the Kibana instance.", + "units": "ms", + "format": "0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1504027460000, + 171.05714416503906 + ], + [ + 1504027470000, + 171.05714416503906 + ], + [ + 1504027480000, + 171.05714416503906 + ], + [ + 1504027490000, + 171.05714416503906 + ], + [ + 1504027500000, + 171.05714416503906 + ], + [ + 1504027510000, + 171.05714416503906 + ], + [ + 1504027520000, + 171.05714416503906 + ], + [ + 1504027530000, + 171.05714416503906 + ], + [ + 1504027540000, + 171.05714416503906 + ] + ] + } + ], + "kibana_requests": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1504027457000, + "max": 1504027568000 + }, + "metric": { + "app": "kibana", + "field": "kibana_stats.requests.total", + "metricAgg": "max", + "label": "Client Requests", + "description": "Total number of client requests received by the Kibana instance.", + "units": "", + "format": "0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1504027460000, + 113 + ], + [ + 1504027470000, + 146 + ], + [ + 1504027480000, + 162 + ], + [ + 1504027490000, + 164 + ], + [ + 1504027500000, + 166 + ], + [ + 1504027510000, + 168 + ], + [ + 1504027520000, + 170 + ], + [ + 1504027530000, + 172 + ], + [ + 1504027540000, + 174 + ] + ] + } + ] + }, + "kibanaSummary": { + "uuid": "de3b8f2a-7bb9-4931-9bf3-997ba7824cf9", + "name": "tsullivan.local", + "index": ".kibana", + "host": "tsullivan.local", + "transport_address": "tsullivan.local:5601", + "version": "7.0.0-alpha1", + "snapshot": false, + "status": "green", + "availability": false, + "os_memory_free": 1645989888, + "uptime": 200102 + } +} diff --git a/x-pack/test/api_integration/apis/monitoring/kibana/fixtures/listing.json b/x-pack/test/api_integration/apis/monitoring/kibana/fixtures/listing.json new file mode 100644 index 00000000000000..87c3bade022c33 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/kibana/fixtures/listing.json @@ -0,0 +1,44 @@ +{ + "clusterStatus": { + "uuids": [ + "de3b8f2a-7bb9-4931-9bf3-997ba7824cf9" + ], + "status": "green", + "requests_total": 174, + "concurrent_connections": 174, + "response_time_max": 2203, + "memory_size": 230227968, + "memory_limit": 1501560832, + "count": 1 + }, + "kibanas": [ + { + "process": { + "memory": { + "resident_set_size_in_bytes": 230227968 + } + }, + "os": { + "load": { + "1m": 3.19091796875 + } + }, + "response_times": { + "average": 171.05714285714285, + "max": 2203 + }, + "requests": { + "total": 174 + }, + "concurrent_connections": 174, + "kibana": { + "transport_address": "tsullivan.local:5601", + "name": "tsullivan.local", + "host": "tsullivan.local", + "uuid": "de3b8f2a-7bb9-4931-9bf3-997ba7824cf9", + "status": "green" + }, + "availability": false + } + ] +} diff --git a/x-pack/test/api_integration/apis/monitoring/kibana/index.js b/x-pack/test/api_integration/apis/monitoring/kibana/index.js index 54b7eb4aae9c80..e71cbacaa17a05 100644 --- a/x-pack/test/api_integration/apis/monitoring/kibana/index.js +++ b/x-pack/test/api_integration/apis/monitoring/kibana/index.js @@ -7,6 +7,8 @@ export default function ({ loadTestFile }) { describe('Kibana', () => { loadTestFile(require.resolve('./overview')); + loadTestFile(require.resolve('./listing')); + loadTestFile(require.resolve('./instance')); }); } diff --git a/x-pack/test/api_integration/apis/monitoring/kibana/instance.js b/x-pack/test/api_integration/apis/monitoring/kibana/instance.js new file mode 100644 index 00000000000000..e0a67839e29698 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/kibana/instance.js @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from 'expect.js'; +import instanceFixture from './fixtures/instance'; + +export default function ({ getService }) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('instance detail', () => { + const archive = 'monitoring/singlecluster-yellow-platinum'; + const timeRange = { + min: '2017-08-29T17:24:17.000Z', + max: '2017-08-29T17:26:08.000Z' + }; + + before('load archive', () => { + return esArchiver.load(archive); + }); + + after('unload archive', () => { + return esArchiver.unload(archive); + }); + + it('should summarize single kibana instance with metrics', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/DFDDUmKHR0Ge0mkdYW2bew/kibana/de3b8f2a-7bb9-4931-9bf3-997ba7824cf9') + .set('kbn-xsrf', 'xxx') + .send({ timeRange }) + .expect(200); + + expect(body).to.eql(instanceFixture); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/monitoring/kibana/listing.js b/x-pack/test/api_integration/apis/monitoring/kibana/listing.js new file mode 100644 index 00000000000000..013f20486d9ae4 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/kibana/listing.js @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from 'expect.js'; +import listingFixture from './fixtures/listing'; + +export default function ({ getService }) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('listing', () => { + const archive = 'monitoring/singlecluster-yellow-platinum'; + const timeRange = { + min: '2017-08-29T17:24:17.000Z', + max: '2017-08-29T17:26:08.000Z' + }; + + before('load archive', () => { + return esArchiver.load(archive); + }); + + after('unload archive', () => { + return esArchiver.unload(archive); + }); + + it('should summarize list of kibana instances with stats', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/DFDDUmKHR0Ge0mkdYW2bew/kibana/instances') + .set('kbn-xsrf', 'xxx') + .send({ timeRange }) + .expect(200); + + expect(body).to.eql(listingFixture); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/monitoring/kibana/overview.js b/x-pack/test/api_integration/apis/monitoring/kibana/overview.js index 83dcf9dd91e8b1..c3e3339623443b 100644 --- a/x-pack/test/api_integration/apis/monitoring/kibana/overview.js +++ b/x-pack/test/api_integration/apis/monitoring/kibana/overview.js @@ -26,7 +26,7 @@ export default function ({ getService }) { return esArchiver.unload(archive); }); - it('should summarize single kibana instance with metrics', async () => { + it('should summarize kibana instances with stats', async () => { const { body } = await supertest .post('/api/monitoring/v1/clusters/DFDDUmKHR0Ge0mkdYW2bew/kibana') .set('kbn-xsrf', 'xxx') diff --git a/x-pack/test/api_integration/apis/monitoring/logstash/fixtures/node_detail.json b/x-pack/test/api_integration/apis/monitoring/logstash/fixtures/node_detail.json new file mode 100644 index 00000000000000..3684ba58586e48 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/logstash/fixtures/node_detail.json @@ -0,0 +1,1883 @@ +{ + "metrics": { + "logstash_os_load": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.os.cpu.load_average.1m", + "metricAgg": "max", + "label": "1m", + "title": "System Load", + "description": "Load average over the last minute.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + 6.5390625 + ], + [ + 1516613610000, + 6 + ], + [ + 1516613620000, + 5.390625 + ], + [ + 1516613630000, + 5.09765625 + ], + [ + 1516613640000, + 4.70703125 + ], + [ + 1516613650000, + 4.48828125 + ], + [ + 1516613660000, + 4.328125 + ], + [ + 1516613670000, + 3.89453125 + ], + [ + 1516613680000, + 4.5546875 + ], + [ + 1516613690000, + 4.2421875 + ], + [ + 1516613700000, + 3.890625 + ], + [ + 1516613710000, + 4 + ], + [ + 1516613720000, + 4.171875 + ], + [ + 1516613730000, + 4.60546875 + ], + [ + 1516613740000, + 4.125 + ], + [ + 1516613750000, + 3.87109375 + ], + [ + 1516613760000, + 3.64453125 + ], + [ + 1516613770000, + 4.12109375 + ], + [ + 1516613780000, + 3.935546875 + ], + [ + 1516613790000, + 4.7578125 + ], + [ + 1516613800000, + 4.33984375 + ], + [ + 1516613810000, + 4.29296875 + ], + [ + 1516613820000, + 3.78515625 + ], + [ + 1516613830000, + 3.6640625 + ], + [ + 1516613840000, + 4.14453125 + ], + [ + 1516613850000, + 4.7109375 + ], + [ + 1516613860000, + 4.29296875 + ], + [ + 1516613870000, + 3.8671875 + ], + [ + 1516613880000, + 4.55078125 + ], + [ + 1516613890000, + 4.296875 + ], + [ + 1516613900000, + 3.951171875 + ], + [ + 1516613910000, + 3.724609375 + ], + [ + 1516613920000, + 3.84765625 + ], + [ + 1516613930000, + 3.857421875 + ], + [ + 1516613940000, + 4.68359375 + ], + [ + 1516613950000, + 5.2265625 + ], + [ + 1516613960000, + 4.9453125 + ], + [ + 1516613970000, + 5.4453125 + ], + [ + 1516613980000, + 5.578125 + ], + [ + 1516613990000, + 5.984375 + ], + [ + 1516614000000, + 5.3671875 + ], + [ + 1516614010000, + 4.84765625 + ], + [ + 1516614020000, + 4.71875 + ], + [ + 1516614030000, + 4.2265625 + ], + [ + 1516614040000, + 5.08984375 + ], + [ + 1516614050000, + 4.5390625 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.os.cpu.load_average.5m", + "metricAgg": "max", + "label": "5m", + "title": "System Load", + "description": "Load average over the last 5 minutes.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + null + ], + [ + 1516613610000, + null + ], + [ + 1516613620000, + null + ], + [ + 1516613630000, + null + ], + [ + 1516613640000, + null + ], + [ + 1516613650000, + null + ], + [ + 1516613660000, + null + ], + [ + 1516613670000, + null + ], + [ + 1516613680000, + null + ], + [ + 1516613690000, + null + ], + [ + 1516613700000, + null + ], + [ + 1516613710000, + null + ], + [ + 1516613720000, + null + ], + [ + 1516613730000, + null + ], + [ + 1516613740000, + null + ], + [ + 1516613750000, + null + ], + [ + 1516613760000, + null + ], + [ + 1516613770000, + null + ], + [ + 1516613780000, + null + ], + [ + 1516613790000, + null + ], + [ + 1516613800000, + null + ], + [ + 1516613810000, + null + ], + [ + 1516613820000, + null + ], + [ + 1516613830000, + null + ], + [ + 1516613840000, + null + ], + [ + 1516613850000, + null + ], + [ + 1516613860000, + null + ], + [ + 1516613870000, + null + ], + [ + 1516613880000, + null + ], + [ + 1516613890000, + null + ], + [ + 1516613900000, + null + ], + [ + 1516613910000, + null + ], + [ + 1516613920000, + null + ], + [ + 1516613930000, + null + ], + [ + 1516613940000, + null + ], + [ + 1516613950000, + null + ], + [ + 1516613960000, + null + ], + [ + 1516613970000, + null + ], + [ + 1516613980000, + null + ], + [ + 1516613990000, + null + ], + [ + 1516614000000, + null + ], + [ + 1516614010000, + null + ], + [ + 1516614020000, + null + ], + [ + 1516614030000, + null + ], + [ + 1516614040000, + null + ], + [ + 1516614050000, + null + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.os.cpu.load_average.15m", + "metricAgg": "max", + "label": "15m", + "title": "System Load", + "description": "Load average over the last 15 minutes.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + null + ], + [ + 1516613610000, + null + ], + [ + 1516613620000, + null + ], + [ + 1516613630000, + null + ], + [ + 1516613640000, + null + ], + [ + 1516613650000, + null + ], + [ + 1516613660000, + null + ], + [ + 1516613670000, + null + ], + [ + 1516613680000, + null + ], + [ + 1516613690000, + null + ], + [ + 1516613700000, + null + ], + [ + 1516613710000, + null + ], + [ + 1516613720000, + null + ], + [ + 1516613730000, + null + ], + [ + 1516613740000, + null + ], + [ + 1516613750000, + null + ], + [ + 1516613760000, + null + ], + [ + 1516613770000, + null + ], + [ + 1516613780000, + null + ], + [ + 1516613790000, + null + ], + [ + 1516613800000, + null + ], + [ + 1516613810000, + null + ], + [ + 1516613820000, + null + ], + [ + 1516613830000, + null + ], + [ + 1516613840000, + null + ], + [ + 1516613850000, + null + ], + [ + 1516613860000, + null + ], + [ + 1516613870000, + null + ], + [ + 1516613880000, + null + ], + [ + 1516613890000, + null + ], + [ + 1516613900000, + null + ], + [ + 1516613910000, + null + ], + [ + 1516613920000, + null + ], + [ + 1516613930000, + null + ], + [ + 1516613940000, + null + ], + [ + 1516613950000, + null + ], + [ + 1516613960000, + null + ], + [ + 1516613970000, + null + ], + [ + 1516613980000, + null + ], + [ + 1516613990000, + null + ], + [ + 1516614000000, + null + ], + [ + 1516614010000, + null + ], + [ + 1516614020000, + null + ], + [ + 1516614030000, + null + ], + [ + 1516614040000, + null + ], + [ + 1516614050000, + null + ] + ] + } + ], + "logstash_events_input_rate": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.events.in", + "metricAgg": "max", + "label": "Events Received Rate", + "description": "Number of events received per second by the Logstash node at the inputs stage.", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1516613600000, + null + ], + [ + 1516613610000, + 162.5 + ], + [ + 1516613620000, + 137.5 + ], + [ + 1516613630000, + 200 + ], + [ + 1516613640000, + 100 + ], + [ + 1516613650000, + 200 + ], + [ + 1516613660000, + 112.5 + ], + [ + 1516613670000, + 187.5 + ], + [ + 1516613680000, + 200 + ], + [ + 1516613690000, + 100 + ], + [ + 1516613700000, + 200 + ], + [ + 1516613710000, + 150 + ], + [ + 1516613720000, + 150 + ], + [ + 1516613730000, + 200 + ], + [ + 1516613740000, + 112.5 + ], + [ + 1516613750000, + 187.5 + ], + [ + 1516613760000, + 200 + ], + [ + 1516613770000, + 100 + ], + [ + 1516613780000, + 200 + ], + [ + 1516613790000, + 125 + ], + [ + 1516613800000, + 175 + ], + [ + 1516613810000, + 200 + ], + [ + 1516613820000, + 112.5 + ], + [ + 1516613830000, + 187.5 + ], + [ + 1516613840000, + 125 + ], + [ + 1516613850000, + 187.5 + ], + [ + 1516613860000, + 175 + ], + [ + 1516613870000, + 137.5 + ], + [ + 1516613880000, + 162.5 + ], + [ + 1516613890000, + 187.5 + ], + [ + 1516613900000, + 137.5 + ], + [ + 1516613910000, + 175 + ], + [ + 1516613920000, + 137.5 + ], + [ + 1516613930000, + 175 + ], + [ + 1516613940000, + 187.5 + ], + [ + 1516613950000, + 137.5 + ], + [ + 1516613960000, + 162.5 + ], + [ + 1516613970000, + 162.5 + ], + [ + 1516613980000, + 162.5 + ], + [ + 1516613990000, + 175 + ], + [ + 1516614000000, + 150 + ], + [ + 1516614010000, + 150 + ], + [ + 1516614020000, + 175 + ], + [ + 1516614030000, + 162.5 + ], + [ + 1516614040000, + 162.5 + ], + [ + 1516614050000, + 162.5 + ] + ] + } + ], + "logstash_events_output_rate": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.events.out", + "metricAgg": "max", + "label": "Events Emitted Rate", + "description": "Number of events emitted per second by the Logstash node at the outputs stage.", + "units": "/s", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1516613600000, + null + ], + [ + 1516613610000, + 162.5 + ], + [ + 1516613620000, + 137.5 + ], + [ + 1516613630000, + 200 + ], + [ + 1516613640000, + 100 + ], + [ + 1516613650000, + 200 + ], + [ + 1516613660000, + 112.5 + ], + [ + 1516613670000, + 187.5 + ], + [ + 1516613680000, + 200 + ], + [ + 1516613690000, + 100 + ], + [ + 1516613700000, + 200 + ], + [ + 1516613710000, + 150 + ], + [ + 1516613720000, + 150 + ], + [ + 1516613730000, + 200 + ], + [ + 1516613740000, + 112.5 + ], + [ + 1516613750000, + 187.5 + ], + [ + 1516613760000, + 200 + ], + [ + 1516613770000, + 100 + ], + [ + 1516613780000, + 200 + ], + [ + 1516613790000, + 125 + ], + [ + 1516613800000, + 175 + ], + [ + 1516613810000, + 200 + ], + [ + 1516613820000, + 112.5 + ], + [ + 1516613830000, + 187.5 + ], + [ + 1516613840000, + 125 + ], + [ + 1516613850000, + 187.5 + ], + [ + 1516613860000, + 175 + ], + [ + 1516613870000, + 137.5 + ], + [ + 1516613880000, + 162.5 + ], + [ + 1516613890000, + 187.5 + ], + [ + 1516613900000, + 137.5 + ], + [ + 1516613910000, + 175 + ], + [ + 1516613920000, + 137.5 + ], + [ + 1516613930000, + 175 + ], + [ + 1516613940000, + 187.5 + ], + [ + 1516613950000, + 137.5 + ], + [ + 1516613960000, + 162.5 + ], + [ + 1516613970000, + 162.5 + ], + [ + 1516613980000, + 162.5 + ], + [ + 1516613990000, + 175 + ], + [ + 1516614000000, + 150 + ], + [ + 1516614010000, + 150 + ], + [ + 1516614020000, + 175 + ], + [ + 1516614030000, + 162.5 + ], + [ + 1516614040000, + 162.5 + ], + [ + 1516614050000, + 162.5 + ] + ] + } + ], + "logstash_events_latency": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.events.out", + "metricAgg": "sum", + "label": "Event Latency", + "description": "Average time spent by events in the filter and output stages, which is the total time it takes to process events divided by number of events emitted.", + "units": "ms", + "format": "0,0.[00]", + "hasCalculation": true, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + null + ], + [ + 1516613610000, + 51.2443076923077 + ], + [ + 1516613620000, + 51.689454545454545 + ], + [ + 1516613630000, + 51.437 + ], + [ + 1516613640000, + 49.005 + ], + [ + 1516613650000, + 50.281499999999994 + ], + [ + 1516613660000, + 49.675555555555555 + ], + [ + 1516613670000, + 50.21013333333333 + ], + [ + 1516613680000, + 49.4585 + ], + [ + 1516613690000, + 50.792 + ], + [ + 1516613700000, + 49.666000000000004 + ], + [ + 1516613710000, + 48.37866666666667 + ], + [ + 1516613720000, + 48.327333333333335 + ], + [ + 1516613730000, + 50.16 + ], + [ + 1516613740000, + 49.28888888888889 + ], + [ + 1516613750000, + 49.42666666666667 + ], + [ + 1516613760000, + 49.582 + ], + [ + 1516613770000, + 50.147 + ], + [ + 1516613780000, + 50.3355 + ], + [ + 1516613790000, + 49.989599999999996 + ], + [ + 1516613800000, + 50.04057142857143 + ], + [ + 1516613810000, + 49.075 + ], + [ + 1516613820000, + 49.78755555555556 + ], + [ + 1516613830000, + 49.56426666666666 + ], + [ + 1516613840000, + 49.4512 + ], + [ + 1516613850000, + 49.48746666666666 + ], + [ + 1516613860000, + 48.75599999999999 + ], + [ + 1516613870000, + 49.84436363636364 + ], + [ + 1516613880000, + 49.11323076923077 + ], + [ + 1516613890000, + 49.962666666666664 + ], + [ + 1516613900000, + 49.05672727272727 + ], + [ + 1516613910000, + 49.56114285714286 + ], + [ + 1516613920000, + 49.39272727272727 + ], + [ + 1516613930000, + 48.95485714285714 + ], + [ + 1516613940000, + 50.08693333333333 + ], + [ + 1516613950000, + 48.75418181818182 + ], + [ + 1516613960000, + 49.68184615384615 + ], + [ + 1516613970000, + 49.61784615384615 + ], + [ + 1516613980000, + 50.027692307692305 + ], + [ + 1516613990000, + 49.42971428571429 + ], + [ + 1516614000000, + 49.81 + ], + [ + 1516614010000, + 49.48133333333333 + ], + [ + 1516614020000, + 49.227999999999994 + ], + [ + 1516614030000, + 49.10707692307692 + ], + [ + 1516614040000, + 49.376615384615384 + ], + [ + 1516614050000, + 49.219076923076926 + ] + ] + } + ], + "logstash_node_cpu_metric": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.process.cpu.percent", + "metricAgg": "max", + "label": "CPU Utilization", + "description": "Percentage of CPU usage reported by the OS (100% is the max).", + "units": "%", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + 4 + ], + [ + 1516613610000, + 0 + ], + [ + 1516613620000, + 1 + ], + [ + 1516613630000, + 1 + ], + [ + 1516613640000, + 3 + ], + [ + 1516613650000, + 0 + ], + [ + 1516613660000, + 0 + ], + [ + 1516613670000, + 0 + ], + [ + 1516613680000, + 0 + ], + [ + 1516613690000, + 0 + ], + [ + 1516613700000, + 1 + ], + [ + 1516613710000, + 0 + ], + [ + 1516613720000, + 0 + ], + [ + 1516613730000, + 0 + ], + [ + 1516613740000, + 0 + ], + [ + 1516613750000, + 0 + ], + [ + 1516613760000, + 0 + ], + [ + 1516613770000, + 0 + ], + [ + 1516613780000, + 0 + ], + [ + 1516613790000, + 0 + ], + [ + 1516613800000, + 0 + ], + [ + 1516613810000, + 0 + ], + [ + 1516613820000, + 0 + ], + [ + 1516613830000, + 0 + ], + [ + 1516613840000, + 0 + ], + [ + 1516613850000, + 0 + ], + [ + 1516613860000, + 1 + ], + [ + 1516613870000, + 0 + ], + [ + 1516613880000, + 0 + ], + [ + 1516613890000, + 0 + ], + [ + 1516613900000, + 0 + ], + [ + 1516613910000, + 0 + ], + [ + 1516613920000, + 0 + ], + [ + 1516613930000, + 0 + ], + [ + 1516613940000, + 0 + ], + [ + 1516613950000, + 0 + ], + [ + 1516613960000, + 0 + ], + [ + 1516613970000, + 0 + ], + [ + 1516613980000, + 0 + ], + [ + 1516613990000, + 0 + ], + [ + 1516614000000, + 0 + ], + [ + 1516614010000, + 0 + ], + [ + 1516614020000, + 0 + ], + [ + 1516614030000, + 0 + ], + [ + 1516614040000, + 0 + ], + [ + 1516614050000, + 0 + ] + ] + } + ], + "logstash_jvm_usage": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.jvm.mem.heap_max_in_bytes", + "metricAgg": "max", + "label": "Max Heap", + "title": "JVM Heap", + "description": "Total heap available to Logstash running in the JVM.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + 1037959168 + ], + [ + 1516613610000, + 1037959168 + ], + [ + 1516613620000, + 1037959168 + ], + [ + 1516613630000, + 1037959168 + ], + [ + 1516613640000, + 1037959168 + ], + [ + 1516613650000, + 1037959168 + ], + [ + 1516613660000, + 1037959168 + ], + [ + 1516613670000, + 1037959168 + ], + [ + 1516613680000, + 1037959168 + ], + [ + 1516613690000, + 1037959168 + ], + [ + 1516613700000, + 1037959168 + ], + [ + 1516613710000, + 1037959168 + ], + [ + 1516613720000, + 1037959168 + ], + [ + 1516613730000, + 1037959168 + ], + [ + 1516613740000, + 1037959168 + ], + [ + 1516613750000, + 1037959168 + ], + [ + 1516613760000, + 1037959168 + ], + [ + 1516613770000, + 1037959168 + ], + [ + 1516613780000, + 1037959168 + ], + [ + 1516613790000, + 1037959168 + ], + [ + 1516613800000, + 1037959168 + ], + [ + 1516613810000, + 1037959168 + ], + [ + 1516613820000, + 1037959168 + ], + [ + 1516613830000, + 1037959168 + ], + [ + 1516613840000, + 1037959168 + ], + [ + 1516613850000, + 1037959168 + ], + [ + 1516613860000, + 1037959168 + ], + [ + 1516613870000, + 1037959168 + ], + [ + 1516613880000, + 1037959168 + ], + [ + 1516613890000, + 1037959168 + ], + [ + 1516613900000, + 1037959168 + ], + [ + 1516613910000, + 1037959168 + ], + [ + 1516613920000, + 1037959168 + ], + [ + 1516613930000, + 1037959168 + ], + [ + 1516613940000, + 1037959168 + ], + [ + 1516613950000, + 1037959168 + ], + [ + 1516613960000, + 1037959168 + ], + [ + 1516613970000, + 1037959168 + ], + [ + 1516613980000, + 1037959168 + ], + [ + 1516613990000, + 1037959168 + ], + [ + 1516614000000, + 1037959168 + ], + [ + 1516614010000, + 1037959168 + ], + [ + 1516614020000, + 1037959168 + ], + [ + 1516614030000, + 1037959168 + ], + [ + 1516614040000, + 1037959168 + ], + [ + 1516614050000, + 1037959168 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.jvm.mem.heap_used_in_bytes", + "metricAgg": "max", + "label": "Used Heap", + "title": "JVM Heap", + "description": "Total heap used by Logstash running in the JVM.", + "units": "B", + "format": "0.0 b", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + 216603328 + ], + [ + 1516613610000, + 246451112 + ], + [ + 1516613620000, + 260906016 + ], + [ + 1516613630000, + 274696256 + ], + [ + 1516613640000, + 286800552 + ], + [ + 1516613650000, + 300018232 + ], + [ + 1516613660000, + 309226936 + ], + [ + 1516613670000, + 326668552 + ], + [ + 1516613680000, + 337595440 + ], + [ + 1516613690000, + 348476416 + ], + [ + 1516613700000, + 361772224 + ], + [ + 1516613710000, + 372699088 + ], + [ + 1516613720000, + 387016576 + ], + [ + 1516613730000, + 399753160 + ], + [ + 1516613740000, + 408389304 + ], + [ + 1516613750000, + 150165008 + ], + [ + 1516613760000, + 160399432 + ], + [ + 1516613770000, + 172281424 + ], + [ + 1516613780000, + 186501768 + ], + [ + 1516613790000, + 196021568 + ], + [ + 1516613800000, + 209343544 + ], + [ + 1516613810000, + 221038088 + ], + [ + 1516613820000, + 232831016 + ], + [ + 1516613830000, + 246808200 + ], + [ + 1516613840000, + 255202336 + ], + [ + 1516613850000, + 268608856 + ], + [ + 1516613860000, + 282041040 + ], + [ + 1516613870000, + 293235776 + ], + [ + 1516613880000, + 306562424 + ], + [ + 1516613890000, + 316384376 + ], + [ + 1516613900000, + 330267864 + ], + [ + 1516613910000, + 343970152 + ], + [ + 1516613920000, + 354219560 + ], + [ + 1516613930000, + 365903600 + ], + [ + 1516613940000, + 378012392 + ], + [ + 1516613950000, + 391445440 + ], + [ + 1516613960000, + 403269056 + ], + [ + 1516613970000, + 414015256 + ], + [ + 1516613980000, + 152571376 + ], + [ + 1516613990000, + 164761496 + ], + [ + 1516614000000, + 176412240 + ], + [ + 1516614010000, + 189126744 + ], + [ + 1516614020000, + 201081072 + ], + [ + 1516614030000, + 213326648 + ], + [ + 1516614040000, + 225366056 + ], + [ + 1516614050000, + 236959904 + ] + ] + } + ] + }, + "nodeSummary": { + "uuid": "838a2ada-1951-4043-8a23-4b450f6160a4", + "name": "Shaunaks-MacBook-Pro.local", + "snapshot": null, + "status": "green", + "version": "7.0.0-alpha1", + "ephemeral_id": "00b8757e-a217-486e-86f4-68497fa7f6df", + "http_address": "127.0.0.1:9601", + "host": "Shaunaks-MacBook-Pro.local", + "pipeline": { + "workers": 8, + "batch_size": 125 + }, + "availability": false, + "events": { + "filtered": 75125, + "in": 78006, + "duration_in_millis": 3729551, + "out": 75125 + }, + "reloads": { + "successes": 0, + "failures": 0 + }, + "uptime": 502472 + } +} diff --git a/x-pack/test/api_integration/apis/monitoring/logstash/fixtures/node_detail_advanced.json b/x-pack/test/api_integration/apis/monitoring/logstash/fixtures/node_detail_advanced.json new file mode 100644 index 00000000000000..87e5c717efca69 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/logstash/fixtures/node_detail_advanced.json @@ -0,0 +1,1881 @@ +{ + "metrics": { + "logstash_node_cpu_utilization": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.process.cpu.percent", + "metricAgg": "max", + "label": "CPU Utilization", + "description": "Percentage of CPU usage reported by the OS (100% is the max).", + "units": "%", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + 4 + ], + [ + 1516613610000, + 0 + ], + [ + 1516613620000, + 1 + ], + [ + 1516613630000, + 1 + ], + [ + 1516613640000, + 3 + ], + [ + 1516613650000, + 0 + ], + [ + 1516613660000, + 0 + ], + [ + 1516613670000, + 0 + ], + [ + 1516613680000, + 0 + ], + [ + 1516613690000, + 0 + ], + [ + 1516613700000, + 1 + ], + [ + 1516613710000, + 0 + ], + [ + 1516613720000, + 0 + ], + [ + 1516613730000, + 0 + ], + [ + 1516613740000, + 0 + ], + [ + 1516613750000, + 0 + ], + [ + 1516613760000, + 0 + ], + [ + 1516613770000, + 0 + ], + [ + 1516613780000, + 0 + ], + [ + 1516613790000, + 0 + ], + [ + 1516613800000, + 0 + ], + [ + 1516613810000, + 0 + ], + [ + 1516613820000, + 0 + ], + [ + 1516613830000, + 0 + ], + [ + 1516613840000, + 0 + ], + [ + 1516613850000, + 0 + ], + [ + 1516613860000, + 1 + ], + [ + 1516613870000, + 0 + ], + [ + 1516613880000, + 0 + ], + [ + 1516613890000, + 0 + ], + [ + 1516613900000, + 0 + ], + [ + 1516613910000, + 0 + ], + [ + 1516613920000, + 0 + ], + [ + 1516613930000, + 0 + ], + [ + 1516613940000, + 0 + ], + [ + 1516613950000, + 0 + ], + [ + 1516613960000, + 0 + ], + [ + 1516613970000, + 0 + ], + [ + 1516613980000, + 0 + ], + [ + 1516613990000, + 0 + ], + [ + 1516614000000, + 0 + ], + [ + 1516614010000, + 0 + ], + [ + 1516614020000, + 0 + ], + [ + 1516614030000, + 0 + ], + [ + 1516614040000, + 0 + ], + [ + 1516614050000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.process.cpu.percent", + "metricAgg": "max", + "label": "Cgroup CPU Utilization", + "title": "CPU Utilization", + "description": "CPU Usage time compared to the CPU quota shown in percentage. If CPU quotas are not set, then no data will be shown.", + "units": "%", + "format": "0,0.[00]", + "hasCalculation": true, + "isDerivative": true + }, + "data": [ + [ + 1516613600000, + null + ], + [ + 1516613610000, + null + ], + [ + 1516613620000, + null + ], + [ + 1516613630000, + null + ], + [ + 1516613640000, + null + ], + [ + 1516613650000, + null + ], + [ + 1516613660000, + null + ], + [ + 1516613670000, + null + ], + [ + 1516613680000, + null + ], + [ + 1516613690000, + null + ], + [ + 1516613700000, + null + ], + [ + 1516613710000, + null + ], + [ + 1516613720000, + null + ], + [ + 1516613730000, + null + ], + [ + 1516613740000, + null + ], + [ + 1516613750000, + null + ], + [ + 1516613760000, + null + ], + [ + 1516613770000, + null + ], + [ + 1516613780000, + null + ], + [ + 1516613790000, + null + ], + [ + 1516613800000, + null + ], + [ + 1516613810000, + null + ], + [ + 1516613820000, + null + ], + [ + 1516613830000, + null + ], + [ + 1516613840000, + null + ], + [ + 1516613850000, + null + ], + [ + 1516613860000, + null + ], + [ + 1516613870000, + null + ], + [ + 1516613880000, + null + ], + [ + 1516613890000, + null + ], + [ + 1516613900000, + null + ], + [ + 1516613910000, + null + ], + [ + 1516613920000, + null + ], + [ + 1516613930000, + null + ], + [ + 1516613940000, + null + ], + [ + 1516613950000, + null + ], + [ + 1516613960000, + null + ], + [ + 1516613970000, + null + ], + [ + 1516613980000, + null + ], + [ + 1516613990000, + null + ], + [ + 1516614000000, + null + ], + [ + 1516614010000, + null + ], + [ + 1516614020000, + null + ], + [ + 1516614030000, + null + ], + [ + 1516614040000, + null + ], + [ + 1516614050000, + null + ] + ] + } + ], + "logstash_node_cgroup_cpu": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.os.cgroup.cpuacct.usage_nanos", + "metricAgg": "max", + "label": "Cgroup Usage", + "title": "Cgroup CPU Performance", + "description": "The usage, reported in nanoseconds, of the Cgroup. Compare this with the throttling to discover issues.", + "units": "ns", + "format": "0,0.[0]a", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1516613600000, + null + ], + [ + 1516613610000, + null + ], + [ + 1516613620000, + null + ], + [ + 1516613630000, + null + ], + [ + 1516613640000, + null + ], + [ + 1516613650000, + null + ], + [ + 1516613660000, + null + ], + [ + 1516613670000, + null + ], + [ + 1516613680000, + null + ], + [ + 1516613690000, + null + ], + [ + 1516613700000, + null + ], + [ + 1516613710000, + null + ], + [ + 1516613720000, + null + ], + [ + 1516613730000, + null + ], + [ + 1516613740000, + null + ], + [ + 1516613750000, + null + ], + [ + 1516613760000, + null + ], + [ + 1516613770000, + null + ], + [ + 1516613780000, + null + ], + [ + 1516613790000, + null + ], + [ + 1516613800000, + null + ], + [ + 1516613810000, + null + ], + [ + 1516613820000, + null + ], + [ + 1516613830000, + null + ], + [ + 1516613840000, + null + ], + [ + 1516613850000, + null + ], + [ + 1516613860000, + null + ], + [ + 1516613870000, + null + ], + [ + 1516613880000, + null + ], + [ + 1516613890000, + null + ], + [ + 1516613900000, + null + ], + [ + 1516613910000, + null + ], + [ + 1516613920000, + null + ], + [ + 1516613930000, + null + ], + [ + 1516613940000, + null + ], + [ + 1516613950000, + null + ], + [ + 1516613960000, + null + ], + [ + 1516613970000, + null + ], + [ + 1516613980000, + null + ], + [ + 1516613990000, + null + ], + [ + 1516614000000, + null + ], + [ + 1516614010000, + null + ], + [ + 1516614020000, + null + ], + [ + 1516614030000, + null + ], + [ + 1516614040000, + null + ], + [ + 1516614050000, + null + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.os.cgroup.cpu.stat.time_throttled_nanos", + "metricAgg": "max", + "label": "Cgroup Throttling", + "title": "Cgroup CPU Performance", + "description": "The amount of throttled time, reported in nanoseconds, of the Cgroup.", + "units": "ns", + "format": "0,0.[0]a", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1516613600000, + null + ], + [ + 1516613610000, + null + ], + [ + 1516613620000, + null + ], + [ + 1516613630000, + null + ], + [ + 1516613640000, + null + ], + [ + 1516613650000, + null + ], + [ + 1516613660000, + null + ], + [ + 1516613670000, + null + ], + [ + 1516613680000, + null + ], + [ + 1516613690000, + null + ], + [ + 1516613700000, + null + ], + [ + 1516613710000, + null + ], + [ + 1516613720000, + null + ], + [ + 1516613730000, + null + ], + [ + 1516613740000, + null + ], + [ + 1516613750000, + null + ], + [ + 1516613760000, + null + ], + [ + 1516613770000, + null + ], + [ + 1516613780000, + null + ], + [ + 1516613790000, + null + ], + [ + 1516613800000, + null + ], + [ + 1516613810000, + null + ], + [ + 1516613820000, + null + ], + [ + 1516613830000, + null + ], + [ + 1516613840000, + null + ], + [ + 1516613850000, + null + ], + [ + 1516613860000, + null + ], + [ + 1516613870000, + null + ], + [ + 1516613880000, + null + ], + [ + 1516613890000, + null + ], + [ + 1516613900000, + null + ], + [ + 1516613910000, + null + ], + [ + 1516613920000, + null + ], + [ + 1516613930000, + null + ], + [ + 1516613940000, + null + ], + [ + 1516613950000, + null + ], + [ + 1516613960000, + null + ], + [ + 1516613970000, + null + ], + [ + 1516613980000, + null + ], + [ + 1516613990000, + null + ], + [ + 1516614000000, + null + ], + [ + 1516614010000, + null + ], + [ + 1516614020000, + null + ], + [ + 1516614030000, + null + ], + [ + 1516614040000, + null + ], + [ + 1516614050000, + null + ] + ] + } + ], + "logstash_node_cgroup_stats": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.os.cgroup.cpu.stat.number_of_elapsed_periods", + "metricAgg": "max", + "label": "Cgroup Elapsed Periods", + "title": "Cgroup CFS Stats", + "description": "The number of sampling periods from the Completely Fair Scheduler (CFS). Compare against the number of times throttled.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1516613600000, + null + ], + [ + 1516613610000, + null + ], + [ + 1516613620000, + null + ], + [ + 1516613630000, + null + ], + [ + 1516613640000, + null + ], + [ + 1516613650000, + null + ], + [ + 1516613660000, + null + ], + [ + 1516613670000, + null + ], + [ + 1516613680000, + null + ], + [ + 1516613690000, + null + ], + [ + 1516613700000, + null + ], + [ + 1516613710000, + null + ], + [ + 1516613720000, + null + ], + [ + 1516613730000, + null + ], + [ + 1516613740000, + null + ], + [ + 1516613750000, + null + ], + [ + 1516613760000, + null + ], + [ + 1516613770000, + null + ], + [ + 1516613780000, + null + ], + [ + 1516613790000, + null + ], + [ + 1516613800000, + null + ], + [ + 1516613810000, + null + ], + [ + 1516613820000, + null + ], + [ + 1516613830000, + null + ], + [ + 1516613840000, + null + ], + [ + 1516613850000, + null + ], + [ + 1516613860000, + null + ], + [ + 1516613870000, + null + ], + [ + 1516613880000, + null + ], + [ + 1516613890000, + null + ], + [ + 1516613900000, + null + ], + [ + 1516613910000, + null + ], + [ + 1516613920000, + null + ], + [ + 1516613930000, + null + ], + [ + 1516613940000, + null + ], + [ + 1516613950000, + null + ], + [ + 1516613960000, + null + ], + [ + 1516613970000, + null + ], + [ + 1516613980000, + null + ], + [ + 1516613990000, + null + ], + [ + 1516614000000, + null + ], + [ + 1516614010000, + null + ], + [ + 1516614020000, + null + ], + [ + 1516614030000, + null + ], + [ + 1516614040000, + null + ], + [ + 1516614050000, + null + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.os.cgroup.cpu.stat.number_of_times_throttled", + "metricAgg": "max", + "label": "Cgroup Throttled Count", + "title": "Cgroup CFS Stats", + "description": "The number of times that the CPU was throttled by the Cgroup.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": true + }, + "data": [ + [ + 1516613600000, + null + ], + [ + 1516613610000, + null + ], + [ + 1516613620000, + null + ], + [ + 1516613630000, + null + ], + [ + 1516613640000, + null + ], + [ + 1516613650000, + null + ], + [ + 1516613660000, + null + ], + [ + 1516613670000, + null + ], + [ + 1516613680000, + null + ], + [ + 1516613690000, + null + ], + [ + 1516613700000, + null + ], + [ + 1516613710000, + null + ], + [ + 1516613720000, + null + ], + [ + 1516613730000, + null + ], + [ + 1516613740000, + null + ], + [ + 1516613750000, + null + ], + [ + 1516613760000, + null + ], + [ + 1516613770000, + null + ], + [ + 1516613780000, + null + ], + [ + 1516613790000, + null + ], + [ + 1516613800000, + null + ], + [ + 1516613810000, + null + ], + [ + 1516613820000, + null + ], + [ + 1516613830000, + null + ], + [ + 1516613840000, + null + ], + [ + 1516613850000, + null + ], + [ + 1516613860000, + null + ], + [ + 1516613870000, + null + ], + [ + 1516613880000, + null + ], + [ + 1516613890000, + null + ], + [ + 1516613900000, + null + ], + [ + 1516613910000, + null + ], + [ + 1516613920000, + null + ], + [ + 1516613930000, + null + ], + [ + 1516613940000, + null + ], + [ + 1516613950000, + null + ], + [ + 1516613960000, + null + ], + [ + 1516613970000, + null + ], + [ + 1516613980000, + null + ], + [ + 1516613990000, + null + ], + [ + 1516614000000, + null + ], + [ + 1516614010000, + null + ], + [ + 1516614020000, + null + ], + [ + 1516614030000, + null + ], + [ + 1516614040000, + null + ], + [ + 1516614050000, + null + ] + ] + } + ], + "logstash_queue_events_count": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.queue.events_count", + "metricAgg": "max", + "label": "Events Queued", + "title": "Persistent Queue Events", + "description": "Average number of events in the persistent queue waiting to be processed by the filter and output stages.", + "units": "", + "format": "0,0.[00]", + "hasCalculation": false, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + 0 + ], + [ + 1516613610000, + 0 + ], + [ + 1516613620000, + 0 + ], + [ + 1516613630000, + 0 + ], + [ + 1516613640000, + 0 + ], + [ + 1516613650000, + 0 + ], + [ + 1516613660000, + 0 + ], + [ + 1516613670000, + 0 + ], + [ + 1516613680000, + 0 + ], + [ + 1516613690000, + 0 + ], + [ + 1516613700000, + 0 + ], + [ + 1516613710000, + 0 + ], + [ + 1516613720000, + 0 + ], + [ + 1516613730000, + 0 + ], + [ + 1516613740000, + 0 + ], + [ + 1516613750000, + 0 + ], + [ + 1516613760000, + 0 + ], + [ + 1516613770000, + 0 + ], + [ + 1516613780000, + 0 + ], + [ + 1516613790000, + 0 + ], + [ + 1516613800000, + 0 + ], + [ + 1516613810000, + 0 + ], + [ + 1516613820000, + 0 + ], + [ + 1516613830000, + 0 + ], + [ + 1516613840000, + 0 + ], + [ + 1516613850000, + 0 + ], + [ + 1516613860000, + 0 + ], + [ + 1516613870000, + 0 + ], + [ + 1516613880000, + 0 + ], + [ + 1516613890000, + 0 + ], + [ + 1516613900000, + 0 + ], + [ + 1516613910000, + 0 + ], + [ + 1516613920000, + 0 + ], + [ + 1516613930000, + 0 + ], + [ + 1516613940000, + 0 + ], + [ + 1516613950000, + 0 + ], + [ + 1516613960000, + 0 + ], + [ + 1516613970000, + 0 + ], + [ + 1516613980000, + 0 + ], + [ + 1516613990000, + 0 + ], + [ + 1516614000000, + 0 + ], + [ + 1516614010000, + 0 + ], + [ + 1516614020000, + 0 + ], + [ + 1516614030000, + 0 + ], + [ + 1516614040000, + 0 + ], + [ + 1516614050000, + 0 + ] + ] + } + ], + "logstash_pipeline_queue_size": [ + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.pipelines.queue.queue_size_in_bytes", + "label": "Queue Size", + "title": "Persistent Queue Size", + "description": "Current size of all persistent queues in the Logstash pipelines on this node.", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": true, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + 0 + ], + [ + 1516613610000, + 0 + ], + [ + 1516613620000, + 0 + ], + [ + 1516613630000, + 0 + ], + [ + 1516613640000, + 0 + ], + [ + 1516613650000, + 0 + ], + [ + 1516613660000, + 0 + ], + [ + 1516613670000, + 0 + ], + [ + 1516613680000, + 0 + ], + [ + 1516613690000, + 0 + ], + [ + 1516613700000, + 0 + ], + [ + 1516613710000, + 0 + ], + [ + 1516613720000, + 0 + ], + [ + 1516613730000, + 0 + ], + [ + 1516613740000, + 0 + ], + [ + 1516613750000, + 0 + ], + [ + 1516613760000, + 0 + ], + [ + 1516613770000, + 0 + ], + [ + 1516613780000, + 0 + ], + [ + 1516613790000, + 0 + ], + [ + 1516613800000, + 0 + ], + [ + 1516613810000, + 0 + ], + [ + 1516613820000, + 0 + ], + [ + 1516613830000, + 0 + ], + [ + 1516613840000, + 0 + ], + [ + 1516613850000, + 0 + ], + [ + 1516613860000, + 0 + ], + [ + 1516613870000, + 0 + ], + [ + 1516613880000, + 0 + ], + [ + 1516613890000, + 0 + ], + [ + 1516613900000, + 0 + ], + [ + 1516613910000, + 0 + ], + [ + 1516613920000, + 0 + ], + [ + 1516613930000, + 0 + ], + [ + 1516613940000, + 0 + ], + [ + 1516613950000, + 0 + ], + [ + 1516613960000, + 0 + ], + [ + 1516613970000, + 0 + ], + [ + 1516613980000, + 0 + ], + [ + 1516613990000, + 0 + ], + [ + 1516614000000, + 0 + ], + [ + 1516614010000, + 0 + ], + [ + 1516614020000, + 0 + ], + [ + 1516614030000, + 0 + ], + [ + 1516614040000, + 0 + ], + [ + 1516614050000, + 0 + ] + ] + }, + { + "bucket_size": "10 seconds", + "timeRange": { + "min": 1516613593000, + "max": 1516614064000 + }, + "metric": { + "app": "logstash", + "field": "logstash_stats.pipelines.queue.max_queue_size_in_bytes", + "label": "Max Queue Size", + "description": "Maximum size set for the persistent queues on this node.", + "units": "B", + "format": "0,0.0 b", + "hasCalculation": true, + "isDerivative": false + }, + "data": [ + [ + 1516613600000, + 0 + ], + [ + 1516613610000, + 0 + ], + [ + 1516613620000, + 0 + ], + [ + 1516613630000, + 0 + ], + [ + 1516613640000, + 0 + ], + [ + 1516613650000, + 0 + ], + [ + 1516613660000, + 0 + ], + [ + 1516613670000, + 0 + ], + [ + 1516613680000, + 0 + ], + [ + 1516613690000, + 0 + ], + [ + 1516613700000, + 0 + ], + [ + 1516613710000, + 0 + ], + [ + 1516613720000, + 0 + ], + [ + 1516613730000, + 0 + ], + [ + 1516613740000, + 0 + ], + [ + 1516613750000, + 0 + ], + [ + 1516613760000, + 0 + ], + [ + 1516613770000, + 0 + ], + [ + 1516613780000, + 0 + ], + [ + 1516613790000, + 0 + ], + [ + 1516613800000, + 0 + ], + [ + 1516613810000, + 0 + ], + [ + 1516613820000, + 0 + ], + [ + 1516613830000, + 0 + ], + [ + 1516613840000, + 0 + ], + [ + 1516613850000, + 0 + ], + [ + 1516613860000, + 0 + ], + [ + 1516613870000, + 0 + ], + [ + 1516613880000, + 0 + ], + [ + 1516613890000, + 0 + ], + [ + 1516613900000, + 0 + ], + [ + 1516613910000, + 0 + ], + [ + 1516613920000, + 0 + ], + [ + 1516613930000, + 0 + ], + [ + 1516613940000, + 0 + ], + [ + 1516613950000, + 0 + ], + [ + 1516613960000, + 0 + ], + [ + 1516613970000, + 0 + ], + [ + 1516613980000, + 0 + ], + [ + 1516613990000, + 0 + ], + [ + 1516614000000, + 0 + ], + [ + 1516614010000, + 0 + ], + [ + 1516614020000, + 0 + ], + [ + 1516614030000, + 0 + ], + [ + 1516614040000, + 0 + ], + [ + 1516614050000, + 0 + ] + ] + } + ] + }, + "nodeSummary": { + "uuid": "838a2ada-1951-4043-8a23-4b450f6160a4", + "name": "Shaunaks-MacBook-Pro.local", + "snapshot": null, + "status": "green", + "version": "7.0.0-alpha1", + "ephemeral_id": "00b8757e-a217-486e-86f4-68497fa7f6df", + "http_address": "127.0.0.1:9601", + "host": "Shaunaks-MacBook-Pro.local", + "pipeline": { + "workers": 8, + "batch_size": 125 + }, + "availability": false, + "events": { + "filtered": 75125, + "in": 78006, + "duration_in_millis": 3729551, + "out": 75125 + }, + "reloads": { + "successes": 0, + "failures": 0 + }, + "uptime": 502472 + } +} diff --git a/x-pack/test/api_integration/apis/monitoring/logstash/fixtures/nodes.json b/x-pack/test/api_integration/apis/monitoring/logstash/fixtures/nodes.json new file mode 100644 index 00000000000000..d51020cb1f9621 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/logstash/fixtures/nodes.json @@ -0,0 +1,98 @@ +{ + "clusterStatus": { + "node_count": 2, + "events_in_total": 120439, + "events_out_total": 114557, + "avg_memory": 2075918336, + "avg_memory_used": 595127568, + "max_uptime": 502472, + "pipeline_count": 4, + "queue_types": { + "memory": 4, + "persisted": 0 + }, + "versions": [ + "7.0.0-alpha1" + ] + }, + "nodes": [ + { + "jvm": { + "mem": { + "heap_used_percent": 24 + } + }, + "logstash": { + "pipeline": { + "batch_size": 125, + "workers": 8 + }, + "http_address": "127.0.0.1:9601", + "name": "Shaunaks-MacBook-Pro.local", + "host": "Shaunaks-MacBook-Pro.local", + "uuid": "838a2ada-1951-4043-8a23-4b450f6160a4", + "version": "7.0.0-alpha1", + "status": "green" + }, + "process": { + "cpu": { + "percent": 0 + } + }, + "os": { + "cpu": { + "load_average": { + "1m": 4.30224609375 + } + } + }, + "events": { + "out": 75125 + }, + "reloads": { + "failures": 0, + "successes": 0 + }, + "availability": false + }, + { + "jvm": { + "mem": { + "heap_used_percent": 33 + } + }, + "logstash": { + "pipeline": { + "batch_size": 125, + "workers": 8 + }, + "http_address": "127.0.0.1:9600", + "name": "Shaunaks-MacBook-Pro.local", + "host": "Shaunaks-MacBook-Pro.local", + "uuid": "29a3dfa6-c146-4534-9bc0-be475d2ce950", + "version": "7.0.0-alpha1", + "status": "green" + }, + "process": { + "cpu": { + "percent": 2 + } + }, + "os": { + "cpu": { + "load_average": { + "1m": 4.416015625 + } + } + }, + "events": { + "out": 39432 + }, + "reloads": { + "failures": 0, + "successes": 0 + }, + "availability": false + } + ] +} diff --git a/x-pack/test/api_integration/apis/monitoring/logstash/index.js b/x-pack/test/api_integration/apis/monitoring/logstash/index.js index 12fb811c14c889..d07e8a812ad57b 100644 --- a/x-pack/test/api_integration/apis/monitoring/logstash/index.js +++ b/x-pack/test/api_integration/apis/monitoring/logstash/index.js @@ -7,6 +7,8 @@ export default function ({ loadTestFile }) { describe('Logstash', () => { loadTestFile(require.resolve('./overview')); + loadTestFile(require.resolve('./nodes')); + loadTestFile(require.resolve('./node_detail')); }); } diff --git a/x-pack/test/api_integration/apis/monitoring/logstash/node_detail.js b/x-pack/test/api_integration/apis/monitoring/logstash/node_detail.js new file mode 100644 index 00000000000000..bbc385e3ba1c95 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/logstash/node_detail.js @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from 'expect.js'; +import nodeDetailFixture from './fixtures/node_detail'; +import nodeDetailAdvancedFixture from './fixtures/node_detail_advanced'; + +export default function ({ getService }) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('node detail', () => { + const archive = 'monitoring/logstash-pipelines'; + const timeRange = { + min: '2018-01-22T09:33:13.000Z', + max: '2018-01-22T09:41:04.000Z' + }; + + before('load archive', () => { + return esArchiver.load(archive); + }); + + after('unload archive', () => { + return esArchiver.unload(archive); + }); + + it('should summarize the Logstash node with non-advanced chart data metrics', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/1rhApLfQShSh3JsNqYCkmA/logstash/node/838a2ada-1951-4043-8a23-4b450f6160a4') + .set('kbn-xsrf', 'xxx') + .send({ timeRange, is_advanced: false }) + .expect(200); + + expect(body).to.eql(nodeDetailFixture); + }); + + it('should summarize the Logstash node with advanced chart data metrics', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/1rhApLfQShSh3JsNqYCkmA/logstash/node/838a2ada-1951-4043-8a23-4b450f6160a4') + .set('kbn-xsrf', 'xxx') + .send({ timeRange, is_advanced: true }) + .expect(200); + + expect(body).to.eql(nodeDetailAdvancedFixture); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/monitoring/logstash/nodes.js b/x-pack/test/api_integration/apis/monitoring/logstash/nodes.js new file mode 100644 index 00000000000000..7709eaeae0c6b9 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/logstash/nodes.js @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from 'expect.js'; +import nodesFixture from './fixtures/nodes'; + +export default function ({ getService }) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('node listing', () => { + const archive = 'monitoring/logstash-pipelines'; + const timeRange = { + min: '2018-01-22T09:33:13.000Z', + max: '2018-01-22T09:41:04.000Z' + }; + + before('load archive', () => { + return esArchiver.load(archive); + }); + + after('unload archive', () => { + return esArchiver.unload(archive); + }); + + it('should summarize the Logstash nodes with stats', async () => { + const { body } = await supertest + .post('/api/monitoring/v1/clusters/1rhApLfQShSh3JsNqYCkmA/logstash/nodes') + .set('kbn-xsrf', 'xxx') + .send({ timeRange }) + .expect(200); + + expect(body).to.eql(nodesFixture); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/reporting/bwc_existing_indexes.js b/x-pack/test/api_integration/apis/reporting/bwc_existing_indexes.js new file mode 100644 index 00000000000000..37294895a89a43 --- /dev/null +++ b/x-pack/test/api_integration/apis/reporting/bwc_existing_indexes.js @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as GenerationUrls from './generation_urls'; + + +/** + * This file tests the situation when a reporting index spans releases. By default reporting indexes are created + * on a weekly basis, but this is configurable so it is possible a user has this set to yearly. In that event, it + * is possible report data is getting posted to an index that was created by a very old version. We don't have a + * reporting index migration plan, so this test is important to ensure BWC, or that in the event we decide to make + * a major change in a major release, we handle it properly. + */ + +export default function ({ getService }) { + const esArchiver = getService('esArchiver'); + const reportingAPI = getService('reportingAPI'); + const usageAPI = getService('usageAPI'); + + describe('BWC report generation into existing indexes', async () => { + let expectedCompletedReportCount; + let cleanupIndexAlias; + + describe('existing 6_2 index', () => { + before('load data and add index alias', async () => { + await reportingAPI.deleteAllReportingIndexes(); + await esArchiver.load('reporting/bwc/6_2'); + + // The index name in the 6_2 archive. + const ARCHIVED_REPORTING_INDEX = '.reporting-2018.03.11'; + cleanupIndexAlias = await reportingAPI.coerceReportsIntoExistingIndex(ARCHIVED_REPORTING_INDEX); + + const stats = await usageAPI.getUsageStats(); + expectedCompletedReportCount = await reportingAPI.getCompletedReportCount(stats); + }); + + after('remove index alias', async () => { + await cleanupIndexAlias(); + }); + + // Might not be great test practice to lump all these jobs together but reporting takes awhile and it'll be + // more efficient to post them all up front, then sequentially. + it('multiple jobs posted', async () => { + const reportPaths = []; + reportPaths.push(await reportingAPI.postJob(GenerationUrls.CSV_DISCOVER_KUERY_AND_FILTER_6_3)); + reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRESERVE_DASHBOARD_FILTER_6_3)); + reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRESERVE_PIE_VISUALIZATION_6_3)); + reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRINT_DASHBOARD_6_3)); + reportPaths.push(await reportingAPI.postJob( + GenerationUrls.PDF_PRINT_PIE_VISUALIZATION_FILTER_AND_SAVED_SEARCH_6_3)); + + await reportingAPI.expectAllJobsToFinishSuccessfully(reportPaths); + }).timeout(1540000); + + it('jobs completed successfully', async () => { + const stats = await usageAPI.getUsageStats(); + expectedCompletedReportCount += 5; + reportingAPI.expectCompletedReportCount(stats, expectedCompletedReportCount); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/reporting/bwc_generation_urls.js b/x-pack/test/api_integration/apis/reporting/bwc_generation_urls.js new file mode 100644 index 00000000000000..dc953b7622704e --- /dev/null +++ b/x-pack/test/api_integration/apis/reporting/bwc_generation_urls.js @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as GenerationUrls from './generation_urls'; + +export default function ({ getService }) { + const reportingAPI = getService('reportingAPI'); + const usageAPI = getService('usageAPI'); + + describe('BWC report generation urls', () => { + describe('6_2', () => { + before(async () => { + await reportingAPI.deleteAllReportingIndexes(); + }); + + // Might not be great test practice to lump all these jobs together but reporting takes awhile and it'll be + // more efficient to post them all up front, then sequentially. + it('multiple jobs posted', async () => { + const reportPaths = []; + reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRINT_DASHBOARD_6_2)); + reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRESERVE_VISUALIZATION_6_2)); + reportPaths.push(await reportingAPI.postJob(GenerationUrls.CSV_DISCOVER_FILTER_QUERY_6_2)); + + await reportingAPI.expectAllJobsToFinishSuccessfully(reportPaths); + }).timeout(1540000); + + it('jobs completed successfully', async () => { + const stats = await usageAPI.getUsageStats(); + reportingAPI.expectCompletedReportCount(stats, 3); + }); + }); + + // 6.3 urls currently being tested as part of the "bwc_existing_indexes" test suite. Reports are time consuming, + // don't replicate tests if we don't need to, so no specific 6_3 url tests here. + }); +} diff --git a/x-pack/test/api_integration/apis/reporting/generate_pdf.js b/x-pack/test/api_integration/apis/reporting/generate_pdf.js deleted file mode 100644 index e7caf9af7fac6e..00000000000000 --- a/x-pack/test/api_integration/apis/reporting/generate_pdf.js +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from 'expect.js'; -import { indexTimestamp } from '../../../../plugins/reporting/server/lib/esqueue/helpers/index_timestamp'; - -function removeWhitespace(str) { - return str.replace(/\s/g, ''); -} - -export default function ({ getService }) { - const supertest = getService('supertest'); - const esSupertest = getService('esSupertest'); - const esArchiver = getService('esArchiver'); - const log = getService('log'); - - async function waitForJobToFinish(downloadReportPath) { - const PDF_IS_PENDING_CODE = 503; - - const statusCode = await new Promise(resolve => { - const intervalId = setInterval(async () => { - - const response = await supertest - .get(downloadReportPath) - .responseType('blob') - .set('kbn-xsrf', 'xxx'); - log.debug(`Report at path ${downloadReportPath} returned code ${response.statusCode}`); - if (response.statusCode !== PDF_IS_PENDING_CODE) { - clearInterval(intervalId); - resolve(response.statusCode); - } - }, 1500); - }); - - expect(statusCode).to.be(200); - } - - describe('generate pdf API', () => { - let downloadReportPath; - let completedReportCount; - - before('load reporting archive', async () => { - await esArchiver.load('reporting/6_2'); - - // If we don't include this archive, the report would generate visualizations with no data. It's included - // here, even though we can't verify how the visualizations actually look, because the existence of data - // means more code paths are tested. Cnsider the bug we ran into when a const keyword remained in an untranspiled - // file. It's possible that without data, the flow of control would never have run into that keyword. - await esArchiver.load('logstash_functional'); - - const { body } = await supertest - .get('/api/_kibana/v1/stats') - .set('kbn-xsrf', 'xxx') - .expect(200); - completedReportCount = body.reporting.status.completed; - }); - - after(async () => { - await esArchiver.unload('reporting/6_2'); - await esArchiver.unload('logstash_functional'); - }); - - describe('with an existing reporting index', async () => { - let timestampForIndex; - let stats; - // The index name in the 6_2 archive. - const ARCHIVED_REPORTING_INDEX = '.reporting-2018.03.11'; - - // Adding an index alias coerces the report to be generated on an existing index which means any new - // index schema won't be applied. This is important if a point release updated the schema. Reports may still - // be inserted into an existing index before the new schema is applied. - before('add index alias', async () => { - timestampForIndex = indexTimestamp('week', '.'); - await esSupertest - .post('/_aliases') - .send({ - actions: [ - { - add: { index: ARCHIVED_REPORTING_INDEX, alias: `.reporting-${timestampForIndex}` } - } - ] - }) - .expect(200); - }); - - after('remove index alias', async () => { - await esSupertest - .post('/_aliases') - .send({ - actions: [ - { - remove: { index: ARCHIVED_REPORTING_INDEX, alias: `.reporting-${timestampForIndex}` } - } - ] - }) - .expect(200); - }); - - it('successfully posts a visualization print layout pdf job url generated from v6.2', async () => { - // Grabbed from a report generation url from 6.2 - const jobParams = removeWhitespace(` - (browserTimezone:America%2FNew_York,layout:(id:print), - objectType:visualization,queryString:%27_g%3D(refreshInterval:(display:Off,pause:!!f,value:0), - time:(from:!%272015-09-19T00:02:06.633Z!%27,interval:auto,mode:absolute,timezone:America%252FNew_York, - to:!%272015-09-24T06:40:33.165Z!%27))%26_a%3D(filters:!!(),linked:!!f,query:(language:lucene,query:!%27!%27), - uiState:(vis:(defaultColors:(!%270%2B-%2B1!%27:!%27rgb(247,252,245)!%27,!%271%2B-%2B2!%27:!%27rgb(199,233,192) - !%27,!%272%2B-%2B3!%27:!%27rgb(116,196,118)!%27,!%273%2B-%2B3!%27:!%27rgb(35,139,69)!%27))), - vis:(aggs:!!((enabled:!!t,id:!%271!%27,params:(),schema:metric,type:count),(enabled:!!t,id:!%272!%27, - params:(field:bytes,missingBucket:!!f,missingBucketLabel:Missing,order:desc,orderBy:!%271!%27, - otherBucket:!!f,otherBucketLabel:Other,size:5),schema:segment,type:terms),(enabled:!!t,id:!%273!%27, - params:(field:ip,missingBucket:!!f,missingBucketLabel:Missing,order:desc,orderBy:!%271!%27, - otherBucket:!!f,otherBucketLabel:Other,size:5),schema:group,type:terms)),params:(addLegend:!!t, - addTooltip:!!t,colorSchema:Greens,colorsNumber:4,colorsRange:!!(),enableHover:!!f,invertColors:!!f, - legendPosition:right,percentageMode:!!f,setColorRange:!!f,times:!!(),type:heatmap, - valueAxes:!!((id:ValueAxis-1,labels:(color:%2523555,rotate:0,show:!!f),scale:(defaultYExtents:!!f, - type:linear),show:!!f,type:value))),title:!%27bytes%2Bheatmap!%27,type:heatmap))%27, - savedObjectId:dae7e680-2891-11e8-88fd-5754aa989b85)`); - - const { body } = await supertest - .post(`/api/reporting/generate/printablePdf?jobParams=${jobParams}`) - .set('kbn-xsrf', 'xxx') - .expect(200); - downloadReportPath = body.path; - }); - - it('report completes', async () => { - await waitForJobToFinish(downloadReportPath); - }).timeout(540000); - - it('successful job marked as completed', async () => { - const { body } = await supertest - .get(`/api/_kibana/v1/stats`) - .set('kbn-xsrf', 'xxx') - .expect(200); - stats = body; - completedReportCount++; - expect(stats.reporting.status.completed).to.be(completedReportCount); - }); - - // These are new stats as of v6.3 so these numbers won't include any of the reports already in the archive. Hence, - // these values won't add up to stats.reporting.status.completed. - it('1 count for visualize app', async () => { - expect(stats.reporting.lastDay.printable_pdf.app.visualization).to.be(1); - expect(stats.reporting.last7Days.printable_pdf.app.visualization).to.be(1); - expect(stats.reporting.printable_pdf.app.visualization).to.be(1); - }); - - it('0 counts for dashboard app', async () => { - expect(stats.reporting.lastDay.printable_pdf.app.dashboard).to.be(0); - expect(stats.reporting.last7Days.printable_pdf.app.dashboard).to.be(0); - expect(stats.reporting.printable_pdf.app.dashboard).to.be(0); - }); - - it('0 counts for preserve layout', async () => { - expect(stats.reporting.lastDay.printable_pdf.layout.preserve_layout).to.be(0); - expect(stats.reporting.last7Days.printable_pdf.layout.preserve_layout).to.be(0); - expect(stats.reporting.printable_pdf.layout.preserve_layout).to.be(0); - }); - - it('1 count for print layout', async () => { - expect(stats.reporting.lastDay.printable_pdf.layout.print).to.be(1); - expect(stats.reporting.last7Days.printable_pdf.layout.print).to.be(1); - expect(stats.reporting.printable_pdf.layout.print).to.be(1); - }); - - it('successfully posts a dashboard preview layout pdf job url generated from v6.2', async () => { - // Grabbed from a report generation url from 6.2 - const jobParams = removeWhitespace(` - (browserTimezone:America%2FNew_York,layout:(dimensions:(height:656,width:1504),id:preserve_layout), - objectType:dashboard,queryString:%27_g%3D(refreshInterval:(display:Off,pause:!!f,value:0), - time:(from:!%272015-09-19T00:02:06.633Z!%27,interval:auto,mode:absolute,timezone:America%252FNew_York, - to:!%272015-09-24T06:40:33.165Z!%27))%26_a%3D(description:!%27!%27,filters:!!(),fullScreenMode:!!f, - options:(darkTheme:!!f,hidePanelTitles:!!f,useMargins:!!t),panels:!!((gridData:(h:3,i:!%271!%27,w:6,x:0,y:0), - id:Visualization-PieChart,panelIndex:!%271!%27,type:visualization,version:!%276.2.3!%27), - (gridData:(h:3,i:!%272!%27,w:6,x:6,y:0),id:Visualization-MetricChart,panelIndex:!%272!%27, - type:visualization,version:!%276.2.3!%27),(gridData:(h:3,i:!%273!%27,w:6,x:0,y:3), - id:Visualization%25E2%2598%25BA-VerticalBarChart,panelIndex:!%273!%27,type:visualization, - version:!%276.2.3!%27),(gridData:(h:3,i:!%274!%27,w:6,x:6,y:3),id:e495f810-2892-11e8-88fd-5754aa989b85, - panelIndex:!%274!%27,type:search,version:!%276.2.3!%27)),query:(language:lucene,query:!%27!%27), - timeRestore:!!t,title:!%27Small%2BReporting%2BDashboard!%27,viewMode:view)%27, - savedObjectId:%276799db00-2893-11e8-88fd-5754aa989b85%27)`); - const { body } = await supertest - .post(`/api/reporting/generate/printablePdf?jobParams=${jobParams}`) - .set('kbn-xsrf', 'xxx') - .expect(200); - - downloadReportPath = body.path; - }); - - it('report completes', async () => { - await waitForJobToFinish(downloadReportPath); - }).timeout(540000); - - describe('stats updated', async () => { - it('with count of completed reports', async () => { - const { body } = await supertest - .get(`/api/_kibana/v1/stats`) - .set('kbn-xsrf', 'xxx') - .expect(200); - stats = body; - completedReportCount++; - expect(stats.reporting.status.completed).to.be(completedReportCount); - }); - - it('with 1 count for dashboard app', async () => { - expect(stats.reporting.lastDay.printable_pdf.app.dashboard).to.be(1); - expect(stats.reporting.last7Days.printable_pdf.app.dashboard).to.be(1); - expect(stats.reporting.printable_pdf.app.dashboard).to.be(1); - }); - - it('with 1 count for preserve layout', async () => { - expect(stats.reporting.lastDay.printable_pdf.layout.preserve_layout).to.be(1); - expect(stats.reporting.last7Days.printable_pdf.layout.preserve_layout).to.be(1); - expect(stats.reporting.printable_pdf.layout.preserve_layout).to.be(1); - }); - }); - }); - - describe('with a new reporting index', async () => { - let timestampForIndex; - let stats; - - before('delete any existing index alias', async () => { - timestampForIndex = indexTimestamp('week', '.'); - await esSupertest - .delete(`/.reporting-${timestampForIndex}`); - }); - - after('delete new reporting indexes', async () => { - await esSupertest - .delete(`/.reporting-${timestampForIndex}`); - }); - - it('successfully posts a visualization print layout pdf job url generated from v6.2', async () => { - // Grabbed from a report generation url from 6.2 - const jobParams = removeWhitespace(` - (browserTimezone:America%2FNew_York,layout:(id:print), - objectType:visualization,queryString:%27_g%3D(refreshInterval:(display:Off,pause:!!f,value:0), - time:(from:!%272015-09-19T00:02:06.633Z!%27,interval:auto,mode:absolute,timezone:America%252FNew_York, - to:!%272015-09-24T06:40:33.165Z!%27))%26_a%3D(filters:!!(),linked:!!f,query:(language:lucene,query:!%27!%27), - uiState:(vis:(defaultColors:(!%270%2B-%2B1!%27:!%27rgb(247,252,245)!%27,!%271%2B-%2B2!%27:!%27rgb(199,233,192) - !%27,!%272%2B-%2B3!%27:!%27rgb(116,196,118)!%27,!%273%2B-%2B3!%27:!%27rgb(35,139,69)!%27))), - vis:(aggs:!!((enabled:!!t,id:!%271!%27,params:(),schema:metric,type:count),(enabled:!!t,id:!%272!%27, - params:(field:bytes,missingBucket:!!f,missingBucketLabel:Missing,order:desc,orderBy:!%271!%27, - otherBucket:!!f,otherBucketLabel:Other,size:5),schema:segment,type:terms),(enabled:!!t,id:!%273!%27, - params:(field:ip,missingBucket:!!f,missingBucketLabel:Missing,order:desc,orderBy:!%271!%27, - otherBucket:!!f,otherBucketLabel:Other,size:5),schema:group,type:terms)),params:(addLegend:!!t, - addTooltip:!!t,colorSchema:Greens,colorsNumber:4,colorsRange:!!(),enableHover:!!f,invertColors:!!f, - legendPosition:right,percentageMode:!!f,setColorRange:!!f,times:!!(),type:heatmap, - valueAxes:!!((id:ValueAxis-1,labels:(color:%2523555,rotate:0,show:!!f),scale:(defaultYExtents:!!f, - type:linear),show:!!f,type:value))),title:!%27bytes%2Bheatmap!%27,type:heatmap))%27, - savedObjectId:dae7e680-2891-11e8-88fd-5754aa989b85)`); - const { body } = await supertest - .post(`/api/reporting/generate/printablePdf?jobParams=${jobParams}`) - .set('kbn-xsrf', 'xxx') - .expect(200); - - downloadReportPath = body.path; - }); - - it('report completes', async () => { - await waitForJobToFinish(downloadReportPath); - }); - - describe('stats updated', async () => { - it('with count of completed reports', async () => { - const { body } = await supertest - .get(`/api/_kibana/v1/stats`) - .set('kbn-xsrf', 'xxx') - .expect(200); - stats = body; - completedReportCount++; - expect(stats.reporting.status.completed).to.be(completedReportCount); - }); - - it('with 2 counts for visualize app', async () => { - expect(stats.reporting.lastDay.printable_pdf.app.visualization).to.be(2); - expect(stats.reporting.last7Days.printable_pdf.app.visualization).to.be(2); - expect(stats.reporting.printable_pdf.app.visualization).to.be(2); - }); - - it('with 2 counts for print layout', async () => { - expect(stats.reporting.lastDay.printable_pdf.layout.print).to.be(2); - expect(stats.reporting.last7Days.printable_pdf.layout.print).to.be(2); - expect(stats.reporting.printable_pdf.layout.print).to.be(2); - }); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/reporting/generation_urls.js b/x-pack/test/api_integration/apis/reporting/generation_urls.js new file mode 100644 index 00000000000000..35bb40089a56fe --- /dev/null +++ b/x-pack/test/api_integration/apis/reporting/generation_urls.js @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// These all have the domain name portion stripped out. The api infrastructure assumes it when we post to it anyhow. + +/* eslint-disable max-len */ +export const PDF_PRINT_DASHBOARD_6_3 = '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,layout:(id:print),objectType:dashboard,relativeUrls:!(%27%2Fapp%2Fkibana%23%2Fdashboard%2F2ae34a60-3dd4-11e8-b2b9-5d5dc1715159%3F_g%3D(refreshInterval:(display:Off,pause:!!f,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(description:!%27!%27,filters:!!(),fullScreenMode:!!f,options:(darkTheme:!!f,hidePanelTitles:!!f,useMargins:!!t),panels:!!((embeddableConfig:(),gridData:(h:15,i:!%271!%27,w:24,x:0,y:0),id:!%27145ced90-3dcb-11e8-8660-4d65aa086b3c!%27,panelIndex:!%271!%27,type:visualization,version:!%276.3.0!%27),(embeddableConfig:(),gridData:(h:15,i:!%272!%27,w:24,x:24,y:0),id:e2023110-3dcb-11e8-8660-4d65aa086b3c,panelIndex:!%272!%27,type:visualization,version:!%276.3.0!%27)),query:(language:lucene,query:!%27!%27),timeRestore:!!f,title:!%27couple%2Bpanels!%27,viewMode:view)%27),title:%27couple%20panels%27)'; +export const PDF_PRESERVE_DASHBOARD_FILTER_6_3 = '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,layout:(dimensions:(height:439,width:1362),id:preserve_layout),objectType:dashboard,relativeUrls:!(%27%2Fapp%2Fkibana%23%2Fdashboard%2F61c58ad0-3dd3-11e8-b2b9-5d5dc1715159%3F_g%3D(refreshInterval:(display:Off,pause:!!f,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(description:!%27!%27,filters:!!((!%27$state!%27:(store:appState),meta:(alias:!!n,disabled:!!f,index:a0f483a0-3dc9-11e8-8660-4d65aa086b3c,key:animal,negate:!!f,params:(query:dog,type:phrase),type:phrase,value:dog),query:(match:(animal:(query:dog,type:phrase))))),fullScreenMode:!!f,options:(darkTheme:!!f,hidePanelTitles:!!f,useMargins:!!t),panels:!!((embeddableConfig:(),gridData:(h:15,i:!%271!%27,w:24,x:0,y:0),id:!%2750643b60-3dd3-11e8-b2b9-5d5dc1715159!%27,panelIndex:!%271!%27,type:visualization,version:!%276.3.0!%27),(embeddableConfig:(),gridData:(h:15,i:!%272!%27,w:24,x:24,y:0),id:a16d1990-3dca-11e8-8660-4d65aa086b3c,panelIndex:!%272!%27,type:search,version:!%276.3.0!%27)),query:(language:lucene,query:!%27!%27),timeRestore:!!t,title:!%27dashboard%2Bwith%2Bfilter!%27,viewMode:view)%27),title:%27dashboard%20with%20filter%27)'; +export const PDF_PRESERVE_PIE_VISUALIZATION_6_3 = '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,layout:(dimensions:(height:441,width:1002),id:preserve_layout),objectType:visualization,relativeUrls:!(%27%2Fapp%2Fkibana%23%2Fvisualize%2Fedit%2F3fe22200-3dcb-11e8-8660-4d65aa086b3c%3F_g%3D(refreshInterval:(display:Off,pause:!!f,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(filters:!!(),linked:!!f,query:(language:lucene,query:!%27!%27),uiState:(),vis:(aggs:!!((enabled:!!t,id:!%271!%27,params:(),schema:metric,type:count),(enabled:!!t,id:!%272!%27,params:(field:bytes,missingBucket:!!f,missingBucketLabel:Missing,order:desc,orderBy:!%271!%27,otherBucket:!!f,otherBucketLabel:Other,size:5),schema:segment,type:terms)),params:(addLegend:!!t,addTooltip:!!t,isDonut:!!t,labels:(last_level:!!t,show:!!f,truncate:100,values:!!t),legendPosition:right,type:pie),title:!%27Rendering%2BTest:%2Bpie!%27,type:pie))%27),title:%27Rendering%20Test:%20pie%27)'; +export const PDF_PRINT_PIE_VISUALIZATION_FILTER_AND_SAVED_SEARCH_6_3 = '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,layout:(id:print),objectType:visualization,relativeUrls:!(%27%2Fapp%2Fkibana%23%2Fvisualize%2Fedit%2Fbefdb6b0-3e59-11e8-9fc3-39e49624228e%3F_g%3D(refreshInterval:(display:Off,pause:!!f,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(filters:!!((!%27$state!%27:(store:appState),meta:(alias:!!n,disabled:!!f,index:a0f483a0-3dc9-11e8-8660-4d65aa086b3c,key:animal.keyword,negate:!!f,params:(query:dog,type:phrase),type:phrase,value:dog),query:(match:(animal.keyword:(query:dog,type:phrase))))),linked:!!t,query:(language:lucene,query:!%27!%27),uiState:(),vis:(aggs:!!((enabled:!!t,id:!%271!%27,params:(),schema:metric,type:count),(enabled:!!t,id:!%272!%27,params:(field:name.keyword,missingBucket:!!f,missingBucketLabel:Missing,order:desc,orderBy:!%271!%27,otherBucket:!!f,otherBucketLabel:Other,size:5),schema:segment,type:terms)),params:(addLegend:!!t,addTooltip:!!t,isDonut:!!t,labels:(last_level:!!t,show:!!f,truncate:100,values:!!t),legendPosition:right,type:pie),title:!%27Filter%2BTest:%2Banimals:%2Blinked%2Bto%2Bsearch%2Bwith%2Bfilter!%27,type:pie))%27),title:%27Filter%20Test:%20animals:%20linked%20to%20search%20with%20filter%27)'; +export const CSV_DISCOVER_KUERY_AND_FILTER_6_3 = '/api/reporting/generate/csv?jobParams=(conflictedTypesFields:!(),fields:!(%27@timestamp%27,agent,bytes,clientip),indexPatternId:%270bf35f60-3dc9-11e8-8660-4d65aa086b3c%27,metaFields:!(_source,_id,_type,_index,_score),searchRequest:(body:(_source:(excludes:!(),includes:!(%27@timestamp%27,agent,bytes,clientip)),docvalue_fields:!(%27@timestamp%27),query:(bool:(filter:!((bool:(minimum_should_match:1,should:!((match:(clientip:%2773.14.212.83%27)))))),must:!((range:(bytes:(gte:100,lt:1000))),(range:(%27@timestamp%27:(format:epoch_millis,gte:1369165215770,lte:1526931615770)))),must_not:!(),should:!())),script_fields:(),sort:!((%27@timestamp%27:(order:desc,unmapped_type:boolean))),stored_fields:!(%27@timestamp%27,agent,bytes,clientip),version:!t),index:%27logstash-*%27),title:%27Bytes%20and%20kuery%20in%20saved%20search%20with%20filter%27,type:search)'; + +export const PDF_PRINT_DASHBOARD_6_2 = '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,layout:(id:print),objectType:dashboard,queryString:%27_g%3D(refreshInterval:(display:Off,pause:!!f,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(description:!%27!%27,filters:!!((!%27$state!%27:(store:appState),meta:(alias:!!n,disabled:!!f,field:isDog,index:a0f483a0-3dc9-11e8-8660-4d65aa086b3c,key:isDog,negate:!!f,params:(value:!!t),type:phrase,value:true),script:(script:(inline:!%27boolean%2Bcompare(Supplier%2Bs,%2Bdef%2Bv)%2B%257Breturn%2Bs.get()%2B%253D%253D%2Bv%3B%257Dcompare(()%2B-%253E%2B%257B%2Breturn%2Bdoc%255B!!!%27animal.keyword!!!%27%255D.value%2B%253D%253D%2B!!!%27dog!!!%27%2B%257D,%2Bparams.value)%3B!%27,lang:painless,params:(value:!!t))))),fullScreenMode:!!f,options:(darkTheme:!!f,hidePanelTitles:!!f,useMargins:!!t),panels:!!((gridData:(h:3,i:!%274!%27,w:6,x:6,y:0),id:edb65990-53ca-11e8-b481-c9426d020fcd,panelIndex:!%274!%27,type:visualization,version:!%276.2.4!%27),(gridData:(h:3,i:!%275!%27,w:6,x:0,y:0),id:!%270644f890-53cb-11e8-b481-c9426d020fcd!%27,panelIndex:!%275!%27,type:visualization,version:!%276.2.4!%27)),query:(language:lucene,query:!%27weightLbs:%253E15!%27),timeRestore:!!t,title:!%27Animal%2BWeights%2B(created%2Bin%2B6.2)!%27,viewMode:view)%27,savedObjectId:%271b2f47b0-53cb-11e8-b481-c9426d020fcd%27)'; +export const PDF_PRESERVE_VISUALIZATION_6_2 = '/api/reporting/generate/printablePdf?jobParams=(browserTimezone:America%2FNew_York,layout:(dimensions:(height:441,width:1002),id:preserve_layout),objectType:visualization,queryString:%27_g%3D(refreshInterval:(display:Off,pause:!!f,value:0),time:(from:!%27Mon%2BApr%2B09%2B2018%2B17:56:08%2BGMT-0400!%27,mode:absolute,to:!%27Wed%2BApr%2B11%2B2018%2B17:56:08%2BGMT-0400!%27))%26_a%3D(filters:!!(),linked:!!f,query:(language:lucene,query:!%27weightLbs:%253E10!%27),uiState:(),vis:(aggs:!!((enabled:!!t,id:!%271!%27,params:(),schema:metric,type:count),(enabled:!!t,id:!%272!%27,params:(field:weightLbs,missingBucket:!!f,missingBucketLabel:Missing,order:desc,orderBy:!%271!%27,otherBucket:!!f,otherBucketLabel:Other,size:5),schema:segment,type:terms)),params:(addLegend:!!t,addTooltip:!!t,isDonut:!!t,labels:(last_level:!!t,show:!!f,truncate:100,values:!!t),legendPosition:right,type:pie),title:!%27Weight%2Bin%2Blbs%2Bpie%2Bcreated%2Bin%2B6.2!%27,type:pie))%27,savedObjectId:%270644f890-53cb-11e8-b481-c9426d020fcd%27)'; +export const CSV_DISCOVER_FILTER_QUERY_6_2 = '/api/reporting/generate/csv?jobParams=(conflictedTypesFields:!(),fields:!(%27@timestamp%27,animal,sound,weightLbs),indexPatternId:a0f483a0-3dc9-11e8-8660-4d65aa086b3c,metaFields:!(_source,_id,_type,_index,_score),searchRequest:(body:(_source:(excludes:!(),includes:!(%27@timestamp%27,animal,sound,weightLbs)),docvalue_fields:!(%27@timestamp%27),query:(bool:(filter:!(),must:!((query_string:(analyze_wildcard:!t,default_field:%27*%27,query:%27weightLbs:%3E10%27)),(match_phrase:(sound.keyword:(query:growl))),(range:(%27@timestamp%27:(format:epoch_millis,gte:1523310968000,lte:1523483768000)))),must_not:!(),should:!())),script_fields:(),sort:!((%27@timestamp%27:(order:desc,unmapped_type:boolean))),stored_fields:!(%27@timestamp%27,animal,sound,weightLbs),version:!t),index:%27animals-*%27),title:%27Search%20created%20in%206.2%27,type:search)'; diff --git a/x-pack/test/api_integration/apis/reporting/index.js b/x-pack/test/api_integration/apis/reporting/index.js index 71109de34fbc69..361394dcbbf085 100644 --- a/x-pack/test/api_integration/apis/reporting/index.js +++ b/x-pack/test/api_integration/apis/reporting/index.js @@ -4,8 +4,28 @@ * you may not use this file except in compliance with the Elastic License. */ -export default function ({ loadTestFile }) { +export default function ({ loadTestFile, getService }) { + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + describe('reporting', () => { - loadTestFile(require.resolve('./generate_pdf')); + before(async () => { + await esArchiver.load('../../../../test/functional/fixtures/es_archiver/dashboard/current/kibana'); + await esArchiver.load('../../../../test/functional/fixtures/es_archiver/dashboard/current/data'); + + await kibanaServer.uiSettings.update({ + 'dateFormat:tz': 'UTC', + 'defaultIndex': '0bf35f60-3dc9-11e8-8660-4d65aa086b3c' + }); + }); + + after(async () => { + await esArchiver.unload('../../../../test/functional/fixtures/es_archiver/dashboard/current/kibana'); + await esArchiver.unload('../../../../test/functional/fixtures/es_archiver/dashboard/current/data'); + }); + + loadTestFile(require.resolve('./bwc_existing_indexes')); + loadTestFile(require.resolve('./bwc_generation_urls')); + loadTestFile(require.resolve('./usage')); }); } diff --git a/x-pack/test/api_integration/apis/reporting/usage.js b/x-pack/test/api_integration/apis/reporting/usage.js new file mode 100644 index 00000000000000..dbe73df9557588 --- /dev/null +++ b/x-pack/test/api_integration/apis/reporting/usage.js @@ -0,0 +1,147 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from 'expect.js'; +import * as GenerationUrls from "./generation_urls"; + +export default function ({ getService }) { + const esArchiver = getService('esArchiver'); + const reportingAPI = getService('reportingAPI'); + const usageAPI = getService('usageAPI'); + + describe('reporting usage', () => { + before(async () => { + await reportingAPI.deleteAllReportingIndexes(); + }); + + describe('initial usage', () => { + let usage; + + before(async () => { + usage = await usageAPI.getUsageStats(); + }); + + it('shows reporting as available and enabled', async () => { + expect(usage.reporting.available).to.be(true); + expect(usage.reporting.enabled).to.be(true); + }); + + it('is using phantom browser', async () => { + expect(usage.reporting.browser_type).to.be('phantom'); + }); + + it('all counts are 0', async () => { + reportingAPI.expectRecentPdfAppStats(usage, 'visualization', 0); + reportingAPI.expectAllTimePdfAppStats(usage, 'visualization', 0); + reportingAPI.expectRecentPdfAppStats(usage, 'dashboard', 0); + reportingAPI.expectAllTimePdfAppStats(usage, 'dashboard', 0); + reportingAPI.expectRecentPdfLayoutStats(usage, 'preserve_layout', 0); + reportingAPI.expectAllTimePdfLayoutStats(usage, 'preserve_layout', 0); + reportingAPI.expectAllTimePdfLayoutStats(usage, 'print', 0); + reportingAPI.expectRecentPdfLayoutStats(usage, 'print', 0); + reportingAPI.expectRecentJobTypeTotalStats(usage, 'csv', 0); + reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'csv', 0); + reportingAPI.expectRecentJobTypeTotalStats(usage, 'printable_pdf', 0); + reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'printable_pdf', 0); + }); + }); + + describe('includes usage from reporting indexes', () => { + it('generated from 6.2', async () => { + await esArchiver.load('reporting/bwc/6_2'); + const usage = await usageAPI.getUsageStats(); + + reportingAPI.expectRecentJobTypeTotalStats(usage, 'csv', 0); + reportingAPI.expectRecentJobTypeTotalStats(usage, 'printable_pdf', 0); + + reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'csv', 1); + reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'printable_pdf', 7); + + // These statistics weren't tracked until 6.3 + reportingAPI.expectRecentPdfAppStats(usage, 'visualization', 0); + reportingAPI.expectRecentPdfAppStats(usage, 'dashboard', 0); + reportingAPI.expectRecentPdfLayoutStats(usage, 'preserve_layout', 0); + reportingAPI.expectRecentPdfLayoutStats(usage, 'print', 0); + reportingAPI.expectAllTimePdfAppStats(usage, 'visualization', 0); + reportingAPI.expectAllTimePdfAppStats(usage, 'dashboard', 0); + reportingAPI.expectAllTimePdfLayoutStats(usage, 'preserve_layout', 0); + reportingAPI.expectAllTimePdfLayoutStats(usage, 'print', 0); + }); + + + it('generated from 6.3', async () => { + await esArchiver.load('reporting/bwc/6_3'); + const usage = await usageAPI.getUsageStats(); + + reportingAPI.expectRecentJobTypeTotalStats(usage, 'csv', 0); + reportingAPI.expectRecentJobTypeTotalStats(usage, 'printable_pdf', 0); + reportingAPI.expectRecentPdfAppStats(usage, 'visualization', 0); + reportingAPI.expectRecentPdfAppStats(usage, 'dashboard', 0); + reportingAPI.expectRecentPdfLayoutStats(usage, 'preserve_layout', 0); + reportingAPI.expectRecentPdfLayoutStats(usage, 'print', 0); + + reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'csv', 3); + reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'printable_pdf', 19); + reportingAPI.expectAllTimePdfAppStats(usage, 'visualization', 3); + reportingAPI.expectAllTimePdfAppStats(usage, 'dashboard', 3); + reportingAPI.expectAllTimePdfLayoutStats(usage, 'preserve_layout', 3); + reportingAPI.expectAllTimePdfLayoutStats(usage, 'print', 3); + }); + }); + + describe('usage updated when new jobs are posted', async () => { + it('post jobs', async () => { + const reportPaths = []; + reportPaths.push(await reportingAPI.postJob(GenerationUrls.CSV_DISCOVER_KUERY_AND_FILTER_6_3)); + reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRESERVE_DASHBOARD_FILTER_6_3)); + reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRESERVE_PIE_VISUALIZATION_6_3)); + reportPaths.push(await reportingAPI.postJob(GenerationUrls.PDF_PRINT_DASHBOARD_6_3)); + reportPaths.push(await reportingAPI.postJob( + GenerationUrls.PDF_PRINT_PIE_VISUALIZATION_FILTER_AND_SAVED_SEARCH_6_3)); + + await reportingAPI.expectAllJobsToFinishSuccessfully(reportPaths); + }).timeout(1540000); + + it('usage updated', async () => { + const usage = await usageAPI.getUsageStats(); + + reportingAPI.expectRecentPdfAppStats(usage, 'visualization', 2); + reportingAPI.expectRecentPdfAppStats(usage, 'dashboard', 2); + reportingAPI.expectRecentPdfLayoutStats(usage, 'preserve_layout', 2); + reportingAPI.expectRecentPdfLayoutStats(usage, 'print', 2); + reportingAPI.expectRecentJobTypeTotalStats(usage, 'csv', 1); + reportingAPI.expectRecentJobTypeTotalStats(usage, 'printable_pdf', 4); + + reportingAPI.expectAllTimePdfAppStats(usage, 'visualization', 5); + reportingAPI.expectAllTimePdfAppStats(usage, 'dashboard', 5); + reportingAPI.expectAllTimePdfLayoutStats(usage, 'preserve_layout', 5); + reportingAPI.expectAllTimePdfLayoutStats(usage, 'print', 5); + reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'csv', 4); + reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'printable_pdf', 23); + }); + }); + + describe('deprecated API', () => { + it('shows correct stats', async () => { + const usage = await usageAPI.getUsageStatsFromDeprecatedPre64Endpoint(); + + reportingAPI.expectRecentPdfAppStats(usage, 'visualization', 2); + reportingAPI.expectRecentPdfAppStats(usage, 'dashboard', 2); + reportingAPI.expectRecentPdfLayoutStats(usage, 'preserve_layout', 2); + reportingAPI.expectRecentPdfLayoutStats(usage, 'print', 2); + reportingAPI.expectRecentJobTypeTotalStats(usage, 'csv', 1); + reportingAPI.expectRecentJobTypeTotalStats(usage, 'printable_pdf', 4); + + reportingAPI.expectAllTimePdfAppStats(usage, 'visualization', 5); + reportingAPI.expectAllTimePdfAppStats(usage, 'dashboard', 5); + reportingAPI.expectAllTimePdfLayoutStats(usage, 'preserve_layout', 5); + reportingAPI.expectAllTimePdfLayoutStats(usage, 'print', 5); + reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'csv', 4); + reportingAPI.expectAllTimeJobTypeTotalStats(usage, 'printable_pdf', 23); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/xpack_main/index.js b/x-pack/test/api_integration/apis/xpack_main/index.js index 52f81492ba837c..696e027b52eebe 100644 --- a/x-pack/test/api_integration/apis/xpack_main/index.js +++ b/x-pack/test/api_integration/apis/xpack_main/index.js @@ -7,6 +7,6 @@ export default function ({ loadTestFile }) { describe('xpack_main', () => { loadTestFile(require.resolve('./telemetry')); - loadTestFile(require.resolve('./stats')); + loadTestFile(require.resolve('./usage')); }); } diff --git a/x-pack/test/api_integration/apis/xpack_main/stats/stats.js b/x-pack/test/api_integration/apis/xpack_main/stats/stats.js deleted file mode 100644 index 63a194a4e04bfc..00000000000000 --- a/x-pack/test/api_integration/apis/xpack_main/stats/stats.js +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from 'expect.js'; - -export default function ({ getService }) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - describe('stats API', () => { - before('load archives', async () => { - // Using this archive because it includes reports as well as a range of visualization types. - await esArchiver.load('reporting/6_2'); - // Not really neccessary to have data indexes, but it feels incomplete to leave out, and it is possible that - // having data available could potentially interefere with the stats api (unlikely... but possible). - await esArchiver.load('logstash_functional'); - }); - - after(async () => { - await esArchiver.unload('reporting/6_2'); - await esArchiver.unload('logstash_functional'); - }); - - describe('from archived data', () => { - let stats; - - before('load stats', async () => { - const { body } = await supertest - .get(`/api/_kibana/v1/stats`) - .set('kbn-xsrf', 'xxx') - .expect(200); - - stats = body; - }); - - it('counts 3 dashboards', async () => { - expect(stats.kibana.dashboard.total).to.be(3); - }); - - it('counts 18 visualizations', async () => { - expect(stats.kibana.visualization.total).to.be(18); - }); - - it('counts 1 saved search', async () => { - expect(stats.kibana.search.total).to.be(1); - }); - - it('counts 1 index pattern', async () => { - expect(stats.kibana.index_pattern.total).to.be(1); - }); - - it('counts 0 timelion_sheets', async () => { - expect(stats.kibana.timelion_sheet.total).to.be(0); - }); - - it('counts 0 graph workspaces', async () => { - expect(stats.kibana.graph_workspace.total).to.be(0); - }); - - it('shows reporting as available and enabled', async () => { - expect(stats.reporting.available).to.be(true); - expect(stats.reporting.enabled).to.be(true); - }); - - it('is using phantom browser', async () => { - expect(stats.reporting.browser_type).to.be('phantom'); - }); - - it('counts 8 total reports', async () => { - expect(stats.reporting._all).to.be(8); - }); - - it('counts 1 csv report', async () => { - expect(stats.reporting.csv.available).to.be(true); - expect(stats.reporting.csv.total).to.be(1); - }); - - it('counts 7 printable_pdf reports', async () => { - expect(stats.reporting.printable_pdf.available).to.be(true); - expect(stats.reporting.printable_pdf.total).to.be(7); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/xpack_main/telemetry/index.js b/x-pack/test/api_integration/apis/xpack_main/telemetry/index.js index a25c5f5efccb48..3f47fdd99bf917 100644 --- a/x-pack/test/api_integration/apis/xpack_main/telemetry/index.js +++ b/x-pack/test/api_integration/apis/xpack_main/telemetry/index.js @@ -5,7 +5,7 @@ */ export default function ({ loadTestFile }) { - describe('telemetry', () => { + describe('Telemetry', () => { loadTestFile(require.resolve('./telemetry')); }); } diff --git a/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry.js b/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry.js index f7530752581fe8..b9e38c5fd5a7b2 100644 --- a/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry.js +++ b/x-pack/test/api_integration/apis/xpack_main/telemetry/telemetry.js @@ -11,7 +11,7 @@ export default function ({ getService }) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - describe('clusters/_stats', () => { + describe('/api/telemetry/v1/clusters/_stats', () => { describe('with trial license clusters', () => { const archive = 'monitoring/multicluster'; const timeRange = { diff --git a/x-pack/test/api_integration/apis/xpack_main/stats/index.js b/x-pack/test/api_integration/apis/xpack_main/usage/index.js similarity index 78% rename from x-pack/test/api_integration/apis/xpack_main/stats/index.js rename to x-pack/test/api_integration/apis/xpack_main/usage/index.js index 265a64dad7d13c..1c342deade18a6 100644 --- a/x-pack/test/api_integration/apis/xpack_main/stats/index.js +++ b/x-pack/test/api_integration/apis/xpack_main/usage/index.js @@ -5,7 +5,8 @@ */ export default function ({ loadTestFile }) { - describe('stats', () => { - loadTestFile(require.resolve('./stats')); + describe('X-Pack Usage', () => { + loadTestFile(require.resolve('./usage')); }); } + diff --git a/x-pack/test/api_integration/apis/xpack_main/usage/usage.js b/x-pack/test/api_integration/apis/xpack_main/usage/usage.js new file mode 100644 index 00000000000000..a550ec14bcb1ea --- /dev/null +++ b/x-pack/test/api_integration/apis/xpack_main/usage/usage.js @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from 'expect.js'; + +export default function ({ getService }) { + const esArchiver = getService('esArchiver'); + const usageAPI = getService('usageAPI'); + + describe('/api/_xpack/usage', () => { + before('load archives', async () => { + await esArchiver.load('../../../../test/functional/fixtures/es_archiver/dashboard/current/kibana'); + }); + + after(async () => { + await esArchiver.unload('../../../../test/functional/fixtures/es_archiver/dashboard/current/kibana'); + }); + + + it('should return xpack usage data', async () => { + const usage = await usageAPI.getUsageStats(); + + expect(usage.cluster_uuid).to.be.a('string'); + expect(usage.kibana.dashboard.total).to.be(26); + expect(usage.kibana.visualization.total).to.be(47); + expect(usage.kibana.search.total).to.be(5); + expect(usage.kibana.index_pattern.total).to.be(3); + expect(usage.kibana.timelion_sheet.total).to.be(0); + expect(usage.kibana.graph_workspace.total).to.be(0); + }); + }); +} diff --git a/x-pack/test/api_integration/config.js b/x-pack/test/api_integration/config.js index c7b30dabd23568..358986a6bb86ba 100644 --- a/x-pack/test/api_integration/config.js +++ b/x-pack/test/api_integration/config.js @@ -4,15 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resolveKibanaPath } from '@kbn/plugin-helpers'; -import { SupertestWithoutAuthProvider } from './services'; +import { + SupertestWithoutAuthProvider, + ReportingAPIProvider, + UsageAPIProvider, +} from './services'; export default async function ({ readConfigFile }) { - // Read the Kibana API integration tests config file so that we can utilize its services. - const kibanaAPITestsConfig = await readConfigFile(resolveKibanaPath('test/api_integration/config.js')); + const kibanaAPITestsConfig = await readConfigFile(require.resolve('../../../test/api_integration/config.js')); const xPackFunctionalTestsConfig = await readConfigFile(require.resolve('../functional/config.js')); - const kibanaFunctionalConfig = await readConfigFile(resolveKibanaPath('test/functional/config.js')); + const kibanaCommonConfig = await readConfigFile(require.resolve('../../../test/common/config.js')); return { testFiles: [require.resolve('./apis')], @@ -21,12 +23,18 @@ export default async function ({ readConfigFile }) { supertest: kibanaAPITestsConfig.get('services.supertest'), esSupertest: kibanaAPITestsConfig.get('services.esSupertest'), supertestWithoutAuth: SupertestWithoutAuthProvider, - es: kibanaFunctionalConfig.get('services.es'), - esArchiver: kibanaFunctionalConfig.get('services.esArchiver'), + es: kibanaCommonConfig.get('services.es'), + esArchiver: kibanaCommonConfig.get('services.esArchiver'), + reportingAPI: ReportingAPIProvider, + usageAPI: UsageAPIProvider, + kibanaServer: kibanaCommonConfig.get('services.kibanaServer'), }, esArchiver: xPackFunctionalTestsConfig.get('esArchiver'), junit: { reportName: 'X-Pack API Integration Tests', }, + env: xPackFunctionalTestsConfig.get('env'), + kbnTestServer: xPackFunctionalTestsConfig.get('kbnTestServer'), + esTestCluster: xPackFunctionalTestsConfig.get('esTestCluster'), }; } diff --git a/x-pack/test/api_integration/services/index.js b/x-pack/test/api_integration/services/index.js index eb3e2cddb88ed2..8c2ef3b84fb954 100644 --- a/x-pack/test/api_integration/services/index.js +++ b/x-pack/test/api_integration/services/index.js @@ -5,3 +5,5 @@ */ export { SupertestWithoutAuthProvider } from './supertest_without_auth'; +export { ReportingAPIProvider } from './reporting_api'; +export { UsageAPIProvider } from './usage_api'; diff --git a/x-pack/test/api_integration/services/reporting_api.js b/x-pack/test/api_integration/services/reporting_api.js new file mode 100644 index 00000000000000..361ed94c5066a9 --- /dev/null +++ b/x-pack/test/api_integration/services/reporting_api.js @@ -0,0 +1,135 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from 'expect.js'; +import { indexTimestamp } from '../../../plugins/reporting/server/lib/esqueue/helpers/index_timestamp'; + +function removeWhitespace(str) { + return str.replace(/\s/g, ''); +} + +export function ReportingAPIProvider({ getService }) { + const log = getService('log'); + const supertest = getService('supertest'); + const esSupertest = getService('esSupertest'); + + return { + async waitForJobToFinish(downloadReportPath) { + log.debug(`Waiting for job to finish: ${downloadReportPath}`); + const JOB_IS_PENDING_CODE = 503; + + const statusCode = await new Promise(resolve => { + const intervalId = setInterval(async () => { + + const response = await supertest + .get(downloadReportPath) + .responseType('blob') + .set('kbn-xsrf', 'xxx'); + log.debug(`Report at path ${downloadReportPath} returned code ${response.statusCode}`); + if (response.statusCode !== JOB_IS_PENDING_CODE) { + clearInterval(intervalId); + resolve(response.statusCode); + } + }, 1500); + }); + + expect(statusCode).to.be(200); + }, + + async expectAllJobsToFinishSuccessfully(jobPaths) { + await Promise.all(jobPaths.map(async (path) => { + await this.waitForJobToFinish(path); + })); + }, + + async postJob(apiPath) { + log.debug(`ReportingAPI.postJob(${apiPath})`); + const { body } = await supertest + .post(removeWhitespace(apiPath)) + .set('kbn-xsrf', 'xxx') + .expect(200); + return body.path; + }, + + /** + * + * @return {Promise} A function to call to clean up the index alias that was added. + */ + async coerceReportsIntoExistingIndex(indexName) { + log.debug(`ReportingAPI.coerceReportsIntoExistingIndex(${indexName})`); + + // Adding an index alias coerces the report to be generated on an existing index which means any new + // index schema won't be applied. This is important if a point release updated the schema. Reports may still + // be inserted into an existing index before the new schema is applied. + const timestampForIndex = indexTimestamp('week', '.'); + await esSupertest + .post('/_aliases') + .send({ + actions: [ + { + add: { index: indexName, alias: `.reporting-${timestampForIndex}` } + } + ] + }) + .expect(200); + + return async () => { + await esSupertest + .post('/_aliases') + .send({ + actions: [ + { + remove: { index: indexName, alias: `.reporting-${timestampForIndex}` } + } + ] + }) + .expect(200); + }; + }, + + async deleteAllReportingIndexes() { + log.debug('ReportingAPI.deleteAllReportingIndexes'); + await esSupertest + .delete('/.reporting*') + .expect(200); + }, + + expectRecentPdfAppStats(stats, app, count) { + expect(stats.reporting.lastDay.printable_pdf.app[app]).to.be(count); + expect(stats.reporting.last7Days.printable_pdf.app[app]).to.be(count); + }, + + expectAllTimePdfAppStats(stats, app, count) { + expect(stats.reporting.printable_pdf.app[app]).to.be(count); + }, + + expectRecentPdfLayoutStats(stats, layout, count) { + expect(stats.reporting.lastDay.printable_pdf.layout[layout]).to.be(count); + expect(stats.reporting.last7Days.printable_pdf.layout[layout]).to.be(count); + }, + + expectAllTimePdfLayoutStats(stats, layout, count) { + expect(stats.reporting.printable_pdf.layout[layout]).to.be(count); + }, + + expectRecentJobTypeTotalStats(stats, jobType, count) { + expect(stats.reporting.lastDay[jobType].total).to.be(count); + expect(stats.reporting.last7Days[jobType].total).to.be(count); + }, + + expectAllTimeJobTypeTotalStats(stats, jobType, count) { + expect(stats.reporting[jobType].total).to.be(count); + }, + + getCompletedReportCount(stats) { + return stats.reporting.status.completed; + }, + + expectCompletedReportCount(stats, count) { + expect(this.getCompletedReportCount(stats)).to.be(count); + } + }; +} diff --git a/x-pack/test/api_integration/services/usage_api.js b/x-pack/test/api_integration/services/usage_api.js new file mode 100644 index 00000000000000..34222928b0378c --- /dev/null +++ b/x-pack/test/api_integration/services/usage_api.js @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + +export function UsageAPIProvider({ getService }) { + const supertest = getService('supertest'); + + return { + async getUsageStats() { + const { body } = await supertest + .get('/api/_xpack/usage') + .set('kbn-xsrf', 'xxx') + .expect(200); + return body; + }, + + async getUsageStatsFromDeprecatedPre64Endpoint() { + const { body } = await supertest + .get('/api/_kibana/v1/stats') + .set('kbn-xsrf', 'xxx') + .expect(200); + return body; + }, + }; +} diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js index 6aafa4dc9d32c5..417ff83a5800f0 100644 --- a/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js +++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_view_mode.js @@ -13,6 +13,7 @@ export default function ({ getService, getPageObjects }) { const log = getService('log'); const find = getService('find'); const testSubjects = getService('testSubjects'); + const dashboardPanelActions = getService('dashboardPanelActions'); const PageObjects = getPageObjects([ 'security', 'common', @@ -136,7 +137,7 @@ export default function ({ getService, getPageObjects }) { }); it('can filter on a visualization', async () => { - await PageObjects.dashboard.setTimepickerInDataRange(); + await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); await PageObjects.dashboard.filterOnPieSlice(); const filters = await PageObjects.dashboard.getFilters(); expect(filters.length).to.equal(1); @@ -163,17 +164,12 @@ export default function ({ getService, getPageObjects }) { }); it('does not show the visualization edit icon', async () => { - const editIconExists = await testSubjects.exists('dashboardPanelEditLink'); - expect(editIconExists).to.be(false); - }); - - it('does not show the visualization move icon', async () => { - const moveIconExists = await testSubjects.exists('dashboardPanelMoveIcon'); - expect(moveIconExists).to.be(false); + const editLinkExists = await dashboardPanelActions.editPanelActionExists(); + expect(editLinkExists).to.be(false); }); it('does not show the visualization delete icon', async () => { - const deleteIconExists = await testSubjects.exists('dashboardPanelRemoveIcon'); + const deleteIconExists = await dashboardPanelActions.removePanelActionExists(); expect(deleteIconExists).to.be(false); }); diff --git a/x-pack/test/functional/apps/grok_debugger/grok_debugger.js b/x-pack/test/functional/apps/grok_debugger/grok_debugger.js index db1a0ed5f7120b..0f81854ec4877f 100644 --- a/x-pack/test/functional/apps/grok_debugger/grok_debugger.js +++ b/x-pack/test/functional/apps/grok_debugger/grok_debugger.js @@ -42,5 +42,43 @@ export default function ({ getService, getPageObjects }) { await grokDebugger.assertEventOutput({ f: 'Seger', m: 'Comma', l: 'Bob' }); }); }); + + describe('syntax highlighting', () => { + it('applies the correct CSS classes', async () => { + const grokPattern = '\\[(?:-|%{NUMBER:bytes:int})\\]'; + + await grokDebugger.setPatternInput(grokPattern); + + const GROK_START = 'grokStart'; + const GROK_PATTERN_NAME = 'grokPatternName'; + const GROK_SEPARATOR = 'grokSeparator'; + const GROK_FIELD_NAME = 'grokFieldName'; + const GROK_FIELD_TYPE = 'grokFieldType'; + const GROK_END = 'grokEnd'; + const GROK_ESCAPE = 'grokEscape'; + const GROK_ESCAPED = 'grokEscaped'; + const GROK_REGEX = 'grokRegex'; + + await grokDebugger.assertPatternInputSyntaxHighlighting([ + { token: GROK_ESCAPE, content: '\\' }, + { token: GROK_ESCAPED, content: '[' }, + { token: GROK_REGEX, content: '(' }, + { token: GROK_REGEX, content: '?' }, + { token: GROK_REGEX, content: ':' }, + { token: GROK_REGEX, content: '|' }, + { token: GROK_START, content: '%{' }, + { token: GROK_PATTERN_NAME, content: 'NUMBER' }, + { token: GROK_SEPARATOR, content: ':' }, + { token: GROK_FIELD_NAME, content: 'bytes' }, + { token: GROK_SEPARATOR, content: ':' }, + { token: GROK_FIELD_TYPE, content: 'int' }, + { token: GROK_END, content: '}' }, + { token: GROK_REGEX, content: ')' }, + { token: GROK_ESCAPE, content: '\\' }, + { token: GROK_ESCAPED, content: ']' }, + ]); + + }); + }); }); } diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js b/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js index 9f8dc478571de0..fff311b1a57275 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/index_detail.js @@ -38,7 +38,7 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it('green status index with full shard allocation', async () => { + it('should have an index summary with green status index with full shard allocation', async () => { await indicesList.clickRowByName('avocado-tweets-2017.10.02'); expect(await indexDetail.getSummary()).to.eql({ @@ -51,7 +51,7 @@ export default function ({ getService, getPageObjects }) { }); }); - it('green status index with single relocating shard', async () => { + it('should have an index summary with green status index with single relocating shard', async () => { await indicesList.clickRowByName('relocation_test'); expect(await indexDetail.getSummary()).to.eql({ @@ -64,7 +64,7 @@ export default function ({ getService, getPageObjects }) { }); }); - it('yellow status index with single unallocated shard', async () => { + it('should have an index summary with yellow status index with single unallocated shard', async () => { await indicesList.clickRowByName('phone-home'); expect(await indexDetail.getSummary()).to.eql({ @@ -96,7 +96,7 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it.skip('shows NA', async () => { + it.skip('should have an index summary with NA for deleted index', async () => { await indicesList.setFilter('deleted'); await indicesList.clickRowByName('many-0001_clruksahirti'); diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js b/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js index deecf4ce9912a3..d45bf954183016 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/indices.js @@ -30,20 +30,20 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it('Elasticsearch Cluster Summary Status shows correct info', async () => { + it('should have an Elasticsearch cluster summary with correct info', async () => { expect(await esClusterSummaryStatus.getContent()).to.eql({ - nodesCount: '1', - indicesCount: '19', - memory: '267.7 MB / 676.8 MB', - totalShards: '46', - unassignedShards: '23', - documentCount: '4,535', - dataSize: '8.6 MB', + nodesCount: 'Nodes: 1', + indicesCount: 'Indices: 19', + memory: 'Memory: 267.7 MB / 676.8 MB', + totalShards: 'Total Shards: 46', + unassignedShards: 'Unassigned Shards: 23', + documentCount: 'Documents: 4,535', + dataSize: 'Data: 8.6 MB', health: 'Health: red', }); }); - it('Indices Table shows correct rows with default sorting', async () => { + it('should have an indices table with correct rows with default sorting', async () => { const rows = await indicesList.getRows(); expect(rows.length).to.be(20); @@ -84,7 +84,7 @@ export default function ({ getService, getPageObjects }) { }); }); - it('Indices Table shows correct rows after sorting by Search Rate Desc', async () => { + it('should show indices table with correct rows after sorting by Search Rate Desc', async () => { await indicesList.clickSearchCol(); await indicesList.clickSearchCol(); @@ -94,26 +94,26 @@ export default function ({ getService, getPageObjects }) { const indicesAll = await indicesList.getIndicesAll(); const tableData = [ /*eslint-disable max-len*/ - { name: 'many-0001_clruksahirti', status: 'Health: Deleted', documentCount: 'N/A', dataSize: 'N/A', indexRate: 'N/A', searchRate: 'N/A', unassignedShards: 'N/A' }, - { name: 'many-0002_emdkmgdeflno', status: 'Health: Deleted', documentCount: 'N/A', dataSize: 'N/A', indexRate: 'N/A', searchRate: 'N/A', unassignedShards: 'N/A' }, - { name: 'many-0003_jbwrztjwhkjt', status: 'Health: Deleted', documentCount: 'N/A', dataSize: 'N/A', indexRate: 'N/A', searchRate: 'N/A', unassignedShards: 'N/A' }, - { name: 'many-0004_wzgjkelqclur', status: 'Health: Deleted', documentCount: 'N/A', dataSize: 'N/A', indexRate: 'N/A', searchRate: 'N/A', unassignedShards: 'N/A' }, - { name: 'many-0005_dnzzblxoumfe', status: 'Health: Deleted', documentCount: 'N/A', dataSize: 'N/A', indexRate: 'N/A', searchRate: 'N/A', unassignedShards: 'N/A' }, - { name: 'many-0006_gkuqbjonkjmg', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '4.08 /s', unassignedShards: '0' }, - { name: 'many-0008_amnscruqlsnu', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '4.08 /s', unassignedShards: '0' }, - { name: 'many-0010_dgnlpqtstfvi', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0' }, - { name: 'many-0012_jwomwdgfpisl', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0' }, - { name: 'many-0014_zrukbrvuluby', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0' }, - { name: 'many-0016_gyvtsyauoqqg', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0' }, - { name: 'many-0018_ipugjcmuagih', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0' }, - { name: 'many-0020_fqfovcnznbus', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0' }, - { name: 'many-0022_dqbcjopzejlk', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0' }, - { name: 'many-0024_rixhhwzyiczb', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0' }, - { name: 'many-0007_milycdknpycp', status: 'Health: red', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: '1' }, - { name: 'many-0009_reolfgzjjtvh', status: 'Health: red', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: '1' }, - { name: 'many-0011_xtkcmlwmxcov', status: 'Health: red', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: '1' }, - { name: 'many-0013_smjuwdkhpduv', status: 'Health: red', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: '1' }, - { name: 'many-0015_vwmrucgzvohb', status: 'Health: red', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: '1' }, + { name: 'many-0006_gkuqbjonkjmg', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '4.08 /s', unassignedShards: '0', }, + { name: 'many-0008_amnscruqlsnu', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '4.08 /s', unassignedShards: '0', }, + { name: 'many-0010_dgnlpqtstfvi', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0', }, + { name: 'many-0012_jwomwdgfpisl', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0', }, + { name: 'many-0014_zrukbrvuluby', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0', }, + { name: 'many-0016_gyvtsyauoqqg', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0', }, + { name: 'many-0018_ipugjcmuagih', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0', }, + { name: 'many-0020_fqfovcnznbus', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0', }, + { name: 'many-0022_dqbcjopzejlk', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0', }, + { name: 'many-0024_rixhhwzyiczb', status: 'Health: green', documentCount: '1', dataSize: '3.7 KB', indexRate: '0 /s', searchRate: '1.95 /s', unassignedShards: '0', }, + { name: 'many-0001_clruksahirti', status: 'Health: Deleted / Closed', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: 'N/A', }, + { name: 'many-0002_emdkmgdeflno', status: 'Health: Deleted / Closed', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: 'N/A', }, + { name: 'many-0003_jbwrztjwhkjt', status: 'Health: Deleted / Closed', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: 'N/A', }, + { name: 'many-0004_wzgjkelqclur', status: 'Health: Deleted / Closed', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: 'N/A', }, + { name: 'many-0005_dnzzblxoumfe', status: 'Health: Deleted / Closed', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: 'N/A', }, + { name: 'many-0007_milycdknpycp', status: 'Health: red', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: '1', }, + { name: 'many-0009_reolfgzjjtvh', status: 'Health: red', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: '1', }, + { name: 'many-0011_xtkcmlwmxcov', status: 'Health: red', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: '1', }, + { name: 'many-0013_smjuwdkhpduv', status: 'Health: red', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: '1', }, + { name: 'many-0015_vwmrucgzvohb', status: 'Health: red', documentCount: '1', dataSize: '3.6 KB', indexRate: '0 /s', searchRate: '0 /s', unassignedShards: '1', }, ]; /*eslint-enable*/ // check the all data in the table @@ -128,14 +128,14 @@ export default function ({ getService, getPageObjects }) { }); }); - it('filters for specific indices', async () => { + it('should filter for specific indices', async () => { await indicesList.setFilter('000'); const rows = await indicesList.getRows(); expect(rows.length).to.be(9); await indicesList.clearFilter(); }); - it('filters for non-existent index', async () => { + it('should filter for non-existent index', async () => { await indicesList.setFilter('foobar'); await indicesList.assertNoData(); await indicesList.clearFilter(); diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js b/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js index 5d70c414298b37..787629d60c9920 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/node_detail.js @@ -36,35 +36,35 @@ export default function ({ getService, getPageObjects }) { await PageObjects.monitoring.clickBreadcrumb('breadcrumbEsNodes'); // return back for next test }); - it('master node with 20 indices and 38 shards', async () => { + it('should show node summary of master node with 20 indices and 38 shards', async () => { await nodesList.clickRowByResolver('jUT5KdxfRbORSCWkb5zjmA'); expect(await nodeDetail.getSummary()).to.eql({ transportAddress: '127.0.0.1:9300', - jvmHeap: 'JVM Heap: 29 %', + jvmHeap: 'JVM Heap: 29%', freeDiskSpace: 'Free Disk Space: 173.9 GB', documentCount: 'Documents: 24.8k', dataSize: 'Data: 50.4 MB', indicesCount: 'Indices: 20', shardsCount: 'Shards: 38', nodeType: 'Type: Master Node', - status: 'Health: Online', + status: 'Status: Online', }); }); - it('data node with 4 indices and 4 shards', async () => { + it('should show node summary of data node with 4 indices and 4 shards', async () => { await nodesList.clickRowByResolver('bwQWH-7IQY-mFPpfoaoFXQ'); expect(await nodeDetail.getSummary()).to.eql({ transportAddress: '127.0.0.1:9302', - jvmHeap: 'JVM Heap: 17 %', + jvmHeap: 'JVM Heap: 17%', freeDiskSpace: 'Free Disk Space: 173.9 GB', documentCount: 'Documents: 240', dataSize: 'Data: 1.4 MB', indicesCount: 'Indices: 4', shardsCount: 'Shards: 4', nodeType: 'Type: Node', - status: 'Health: Online', + status: 'Status: Online', }); }); }); @@ -87,7 +87,7 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it('shows NA', async () => { + it('should show node summary of NA for offline node', async () => { await nodesList.clickRowByResolver('1jxg5T33TWub-jJL4qP0Wg'); expect(await nodeDetail.getSummary()).to.eql({ @@ -99,7 +99,7 @@ export default function ({ getService, getPageObjects }) { indicesCount: 'Indices: N/A', shardsCount: 'Shards: N/A', nodeType: 'Type: Offline Node', - status: 'Health: Offline', + status: 'Status: Offline', }); }); }); diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js index c5503ad2e567b1..82f4071d9eca91 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes.js @@ -30,18 +30,17 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it('Elasticsearch Cluster Summary Status shows correct info', async () => { + it('should have an Elasticsearch Cluster Summary Status with correct info', async () => { expect(await esClusterSummaryStatus.getContent()).to.eql({ - nodesCount: '3', - indicesCount: '20', - memory: '575.3 MB / 2.0 GB', - totalShards: '80', - unassignedShards: '5', - documentCount: '25,927', - dataSize: '101.6 MB', + nodesCount: 'Nodes: 3', + indicesCount: 'Indices: 20', + memory: 'Memory: 575.3 MB / 2.0 GB', + totalShards: 'Total Shards: 80', + unassignedShards: 'Unassigned Shards: 5', + documentCount: 'Documents: 25,927', + dataSize: 'Data: 101.6 MB', health: 'Health: yellow', }); }); - }); } diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js b/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js index 036ead8139d00b..3dbf003a7b0d8c 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/overview.js @@ -30,16 +30,16 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it('Cluster Summary Status shows correct info', async () => { + it('should have an Elasticsearch Cluster Summary Status with correct info', async () => { expect(await esClusterSummaryStatus.getContent()).to.eql({ - nodesCount: '3', - indicesCount: '20', - memory: '575.3 MB / 2.0 GB', - totalShards: '80', - unassignedShards: '5', - documentCount: '25,927', - dataSize: '101.6 MB', - health: 'yellow', + nodesCount: 'Nodes: 3', + indicesCount: 'Indices: 20', + memory: 'Memory: 575.3 MB / 2.0 GB', + totalShards: 'Total Shards: 80', + unassignedShards: 'Unassigned Shards: 5', + documentCount: 'Documents: 25,927', + dataSize: 'Data: 101.6 MB', + health: 'Health: yellow', }); }); }); diff --git a/x-pack/test/functional/apps/monitoring/kibana/instance.js b/x-pack/test/functional/apps/monitoring/kibana/instance.js index ef5890fe4e3a0a..9429bc97e8079d 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/instance.js +++ b/x-pack/test/functional/apps/monitoring/kibana/instance.js @@ -34,12 +34,12 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it('Kibana Instance Summary Status shows correct info', async () => { + it('should have Instance Summary Status showing correct info', async () => { expect(await instance.getSummary()).to.eql({ transportAddress: 'tsullivan.local:5601', - osFreeMemory: '1.5 GB', - version: '7.0.0-alpha1', - uptime: '3 minutes', + osFreeMemory: 'OS Free Memory: 1.5 GB', + version: 'Version: 7.0.0-alpha1', + uptime: 'Uptime: 3 minutes', health: 'Health: green', }); }); diff --git a/x-pack/test/functional/apps/monitoring/kibana/instances.js b/x-pack/test/functional/apps/monitoring/kibana/instances.js index cb5c95b4c813cb..7372ff816d9878 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/instances.js +++ b/x-pack/test/functional/apps/monitoring/kibana/instances.js @@ -30,13 +30,13 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it('Kibana Cluster Summary Status shows correct info', async () => { + it('should have Kibana Cluster Summary Status showing correct info', async () => { expect(await kibanaClusterSummaryStatus.getContent()).to.eql({ - instances: '1', - memory: '219.7 MB / 1.4 GB', - requests: '172', - connections: '162', - maxResponseTime: '2203 ms', + instances: 'Instances: 1', + memory: 'Memory: 219.6 MB / 1.4 GB', + requests: 'Requests: 174', + connections: 'Connections: 174', + maxResponseTime: 'Max. Response Time: 2203 ms', health: 'Health: green', }); }); diff --git a/x-pack/test/functional/apps/monitoring/kibana/overview.js b/x-pack/test/functional/apps/monitoring/kibana/overview.js index 099c9d9bbfb6b0..a1e884f90b2f0a 100644 --- a/x-pack/test/functional/apps/monitoring/kibana/overview.js +++ b/x-pack/test/functional/apps/monitoring/kibana/overview.js @@ -30,13 +30,13 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it('Kibana Cluster Summary Status shows correct info', async () => { + it('should have Kibana Cluster Summary Status showing correct info', async () => { expect(await kibanaClusterSummaryStatus.getContent()).to.eql({ - instances: '1', - memory: '219.7 MB / 1.4 GB', - requests: '172', - connections: '162', - maxResponseTime: '2203 ms', + instances: 'Instances: 1', + memory: 'Memory: 219.6 MB / 1.4 GB', + requests: 'Requests: 174', + connections: 'Connections: 174', + maxResponseTime: 'Max. Response Time: 2203 ms', health: 'Health: green', }); }); diff --git a/x-pack/test/functional/apps/monitoring/logstash/pipelines.js b/x-pack/test/functional/apps/monitoring/logstash/pipelines.js index 499b366cb39f70..7524032df703fb 100644 --- a/x-pack/test/functional/apps/monitoring/logstash/pipelines.js +++ b/x-pack/test/functional/apps/monitoring/logstash/pipelines.js @@ -30,16 +30,16 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it('Logstash Cluster Summary Status shows correct info', async () => { + it('should have Logstash Cluster Summary Status showing correct info', async () => { expect(await lsClusterSummaryStatus.getContent()).to.eql({ - nodeCount: '2', - memoryUsed: '528.4 MB / 1.9 GB', - eventsInTotal: '117.9k', - eventsOutTotal: '111.9k' + nodeCount: 'Nodes: 2', + memoryUsed: 'Memory: 528.4 MB / 1.9 GB', + eventsInTotal: 'Events Received: 117.9k', + eventsOutTotal: 'Events Emitted: 111.9k' }); }); - it('Pipelines table shows correct rows with default sorting', async () => { + it('should have Pipelines table showing correct rows with default sorting', async () => { const rows = await pipelinesList.getRows(); expect(rows.length).to.be(4); @@ -60,7 +60,7 @@ export default function ({ getService, getPageObjects }) { }); }); - it('Pipelines Table shows correct rows after sorting by Events Emitted Rate Asc', async () => { + it('should have Pipelines Table showing correct rows after sorting by Events Emitted Rate Asc', async () => { await pipelinesList.clickEventsEmittedRateCol(); const rows = await pipelinesList.getRows(); @@ -83,14 +83,14 @@ export default function ({ getService, getPageObjects }) { }); }); - it('filters for specific pipelines', async () => { + it('should filter for specific pipelines', async () => { await pipelinesList.setFilter('la'); const rows = await pipelinesList.getRows(); expect(rows.length).to.be(2); await pipelinesList.clearFilter(); }); - it('filters for non-existent pipeline', async () => { + it('should filter for non-existent pipeline', async () => { await pipelinesList.setFilter('foobar'); await pipelinesList.assertNoData(); await pipelinesList.clearFilter(); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index bf6b2d27a7fb2c..9c9b531ab84b2c 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -7,7 +7,7 @@ /* eslint-disable kibana-custom/no-default-export */ import { resolve } from 'path'; -import { resolveKibanaPath } from '@kbn/plugin-helpers'; +import { format as formatUrl } from 'url'; import { SecurityPageProvider, @@ -53,10 +53,36 @@ import { // that returns an object with the projects config values export default async function ({ readConfigFile }) { - // read the Kibana config file so that we can utilize some of - // its services and PageObjects - const kibanaConfig = await readConfigFile(resolveKibanaPath('test/functional/config.js')); - const kibanaAPITestsConfig = await readConfigFile(resolveKibanaPath('test/api_integration/config.js')); + const kibanaCommonConfig = await readConfigFile(require.resolve('../../../test/common/config.js')); + const kibanaFunctionalConfig = await readConfigFile(require.resolve('../../../test/functional/config.js')); + const kibanaAPITestsConfig = await readConfigFile(require.resolve('../../../test/api_integration/config.js')); + + const servers = { + elasticsearch: { + protocol: process.env.TEST_ES_PROTOCOL || 'http', + hostname: process.env.TEST_ES_HOSTNAME || 'localhost', + port: parseInt(process.env.TEST_ES_PORT, 10) || 9240, + auth: 'elastic:changeme', + username: 'elastic', + password: 'changeme', + }, + kibana: { + protocol: process.env.TEST_KIBANA_PROTOCOL || 'http', + hostname: process.env.TEST_KIBANA_HOSTNAME || 'localhost', + port: parseInt(process.env.TEST_KIBANA_PORT, 10) || 5640, + auth: 'elastic:changeme', + username: 'elastic', + password: 'changeme', + }, + }; + + const env = { + kibana: { + server: { + uuid: '5b2de169-2785-441b-ae8c-186a1936b17d', // Kibana UUID for "primary" cluster in monitoring data + } + } + }; return { // list paths to the files that contain your plugins tests @@ -75,7 +101,7 @@ export default async function ({ readConfigFile }) { // available to your tests. If you don't specify anything here // only the built-in services will be avaliable services: { - ...kibanaConfig.get('services'), + ...kibanaFunctionalConfig.get('services'), esSupertest: kibanaAPITestsConfig.get('services.esSupertest'), monitoringNoData: MonitoringNoDataProvider, monitoringClusterList: MonitoringClusterListProvider, @@ -108,7 +134,7 @@ export default async function ({ readConfigFile }) { // just like services, PageObjects are defined as a map of // names to Providers. Merge in Kibana's or pick specific ones pageObjects: { - ...kibanaConfig.get('pageObjects'), + ...kibanaFunctionalConfig.get('pageObjects'), security: SecurityPageProvider, reporting: ReportingPageProvider, monitoring: MonitoringPageProvider, @@ -118,26 +144,29 @@ export default async function ({ readConfigFile }) { watcher: WatcherPageProvider, }, - servers: { - elasticsearch: { - port: 9240, - auth: 'elastic:changeme', - username: 'elastic', - password: 'changeme', - }, - kibana: { - port: 5640, - auth: 'elastic:changeme', - username: 'elastic', - password: 'changeme', - }, + servers, + + env, + + esTestCluster: { + license: 'trial', + from: 'source', + serverArgs: [ + 'xpack.license.self_generated.type=trial', + 'xpack.security.enabled=true', + ], }, - env: { - kibana: { - server: { - uuid: '5b2de169-2785-441b-ae8c-186a1936b17d', // Kibana UUID for "primary" cluster in monitoring data - } - } + + kbnTestServer: { + ...kibanaCommonConfig.get('kbnTestServer'), + serverArgs: [ + ...kibanaCommonConfig.get('kbnTestServer.serverArgs'), + `--server.uuid=${env.kibana.server.uuid}`, + `--server.port=${servers.kibana.port}`, + `--elasticsearch.url=${formatUrl(servers.elasticsearch)}`, + '--xpack.xpack_main.telemetry.enabled=false', + '--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"', // server restarts should not invalidate active sessions + ], }, // the apps section defines the urls that @@ -145,7 +174,7 @@ export default async function ({ readConfigFile }) { // Merge urls for your plugin with the urls defined in // Kibana's config in order to use this helper apps: { - ...kibanaConfig.get('apps'), + ...kibanaFunctionalConfig.get('apps'), login: { pathname: '/login' }, diff --git a/x-pack/test/functional/es_archives/reporting/6_2/data.json.gz b/x-pack/test/functional/es_archives/reporting/6_2/data.json.gz deleted file mode 100644 index 662c8aa3b4d57a..00000000000000 Binary files a/x-pack/test/functional/es_archives/reporting/6_2/data.json.gz and /dev/null differ diff --git a/x-pack/test/functional/es_archives/reporting/bwc/6_2/data.json.gz b/x-pack/test/functional/es_archives/reporting/bwc/6_2/data.json.gz new file mode 100644 index 00000000000000..a953e82525bd1c Binary files /dev/null and b/x-pack/test/functional/es_archives/reporting/bwc/6_2/data.json.gz differ diff --git a/x-pack/test/functional/es_archives/reporting/bwc/6_2/mappings.json b/x-pack/test/functional/es_archives/reporting/bwc/6_2/mappings.json new file mode 100644 index 00000000000000..5fc2b2dd7fe90f --- /dev/null +++ b/x-pack/test/functional/es_archives/reporting/bwc/6_2/mappings.json @@ -0,0 +1,70 @@ +{ + "type": "index", + "value": { + "index": ".reporting-2018.03.11", + "settings": { + "index": { + "number_of_shards": "1", + "auto_expand_replicas": "0-1", + "number_of_replicas": "0" + } + }, + "mappings": { + "esqueue": { + "properties": { + "attempts": { + "type": "short" + }, + "completed_at": { + "type": "date" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "jobtype": { + "type": "keyword" + }, + "max_attempts": { + "type": "short" + }, + "output": { + "properties": { + "content": { + "type": "object", + "enabled": false + }, + "content_type": { + "type": "keyword" + }, + "max_size_reached": { + "type": "boolean" + } + } + }, + "payload": { + "type": "object", + "enabled": false + }, + "priority": { + "type": "byte" + }, + "process_expiration": { + "type": "date" + }, + "started_at": { + "type": "date" + }, + "status": { + "type": "keyword" + }, + "timeout": { + "type": "long" + } + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/functional/es_archives/reporting/bwc/6_3/data.json.gz b/x-pack/test/functional/es_archives/reporting/bwc/6_3/data.json.gz new file mode 100644 index 00000000000000..0b567d8c6a9cef Binary files /dev/null and b/x-pack/test/functional/es_archives/reporting/bwc/6_3/data.json.gz differ diff --git a/x-pack/test/functional/es_archives/reporting/bwc/6_3/mappings.json b/x-pack/test/functional/es_archives/reporting/bwc/6_3/mappings.json new file mode 100644 index 00000000000000..26faaa7d7be47f --- /dev/null +++ b/x-pack/test/functional/es_archives/reporting/bwc/6_3/mappings.json @@ -0,0 +1,92 @@ +{ + "type": "index", + "value": { + "index": ".reporting-2018.05.06", + "settings": { + "index": { + "number_of_shards": "1", + "auto_expand_replicas": "0-1", + "number_of_replicas": "0" + } + }, + "mappings": { + "esqueue": { + "properties": { + "attempts": { + "type": "short" + }, + "completed_at": { + "type": "date" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "jobtype": { + "type": "keyword" + }, + "max_attempts": { + "type": "short" + }, + "meta": { + "properties": { + "layout": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "objectType": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "output": { + "properties": { + "content": { + "type": "object", + "enabled": false + }, + "content_type": { + "type": "keyword" + }, + "max_size_reached": { + "type": "boolean" + } + } + }, + "payload": { + "type": "object", + "enabled": false + }, + "priority": { + "type": "byte" + }, + "process_expiration": { + "type": "date" + }, + "started_at": { + "type": "date" + }, + "status": { + "type": "keyword" + }, + "timeout": { + "type": "long" + } + } + } + } + } +} diff --git a/x-pack/test/functional/es_archives/reporting/current/reporting/data.json.gz b/x-pack/test/functional/es_archives/reporting/current/reporting/data.json.gz new file mode 100644 index 00000000000000..02028bee8ecec0 Binary files /dev/null and b/x-pack/test/functional/es_archives/reporting/current/reporting/data.json.gz differ diff --git a/x-pack/test/functional/es_archives/reporting/current/reporting/mappings.json b/x-pack/test/functional/es_archives/reporting/current/reporting/mappings.json new file mode 100644 index 00000000000000..e47a7c789a8eea --- /dev/null +++ b/x-pack/test/functional/es_archives/reporting/current/reporting/mappings.json @@ -0,0 +1,92 @@ +{ + "type": "index", + "value": { + "index": ".reporting-2018.05.06", + "settings": { + "index": { + "number_of_shards": "1", + "auto_expand_replicas": "0-1", + "number_of_replicas": "0" + } + }, + "mappings": { + "esqueue": { + "properties": { + "attempts": { + "type": "short" + }, + "completed_at": { + "type": "date" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "jobtype": { + "type": "keyword" + }, + "max_attempts": { + "type": "short" + }, + "meta": { + "properties": { + "layout": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "objectType": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "output": { + "properties": { + "content": { + "type": "object", + "enabled": false + }, + "content_type": { + "type": "keyword" + }, + "max_size_reached": { + "type": "boolean" + } + } + }, + "payload": { + "type": "object", + "enabled": false + }, + "priority": { + "type": "byte" + }, + "process_expiration": { + "type": "date" + }, + "started_at": { + "type": "date" + }, + "status": { + "type": "keyword" + }, + "timeout": { + "type": "long" + } + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/functional/page_objects/security_page.js b/x-pack/test/functional/page_objects/security_page.js index dbf1135f2efdf8..c2e45fcdf92153 100644 --- a/x-pack/test/functional/page_objects/security_page.js +++ b/x-pack/test/functional/page_objects/security_page.js @@ -346,7 +346,7 @@ export function SecurityPageProvider({ getService, getPageObjects }) { log.debug('Delete user ' + username); return remote.findDisplayedByLinkText(username).click() .then(() => { - return PageObjects.header.isGlobalLoadingIndicatorHidden(); + return PageObjects.header.awaitGlobalLoadingIndicatorHidden(); }) .then(() => { log.debug('Find delete button and click'); diff --git a/x-pack/test/functional/services/grok_debugger.js b/x-pack/test/functional/services/grok_debugger.js index d4e09db100ff14..b572e455cb6518 100644 --- a/x-pack/test/functional/services/grok_debugger.js +++ b/x-pack/test/functional/services/grok_debugger.js @@ -61,5 +61,23 @@ export function GrokDebuggerProvider({ getService }) { expect(value).to.eql(expectedValue); }); } + + async assertPatternInputSyntaxHighlighting(expectedHighlights) { + const patternInputElement = await testSubjects.find(SUBJ_UI_ACE_PATTERN_INPUT); + const highlightedElements = await patternInputElement.findAllByXpath('.//div[@class="ace_line"]/*'); + + expect(highlightedElements.length).to.be(expectedHighlights.length); + await Promise.all(highlightedElements.map(async (element, index) => { + const highlightClass = await element.getAttribute('class'); + const highlightedContent = await element.getVisibleText(); + + const expectedHighlight = expectedHighlights[index]; + const expectedHighlightClass = `ace_${expectedHighlight.token}`; + const expectedHighlightedContent = expectedHighlight.content; + + expect(highlightClass).to.be(expectedHighlightClass); + expect(highlightedContent).to.be(expectedHighlightedContent); + })); + } }; } diff --git a/x-pack/test/functional/services/monitoring/elasticsearch_index_detail.js b/x-pack/test/functional/services/monitoring/elasticsearch_index_detail.js index 6fd805720d4038..1fa154b1975adc 100644 --- a/x-pack/test/functional/services/monitoring/elasticsearch_index_detail.js +++ b/x-pack/test/functional/services/monitoring/elasticsearch_index_detail.js @@ -7,7 +7,7 @@ export function MonitoringElasticsearchIndexDetailProvider({ getService }) { const testSubjects = getService('testSubjects'); - const SUBJ_SUMMARY = 'elasticsearchIndexSummaryStatus'; + const SUBJ_SUMMARY = 'elasticsearchIndexDetailStatus'; const SUBJ_SUMMARY_DATA_SIZE = `${SUBJ_SUMMARY} dataSize`; const SUBJ_SUMMARY_DATA_SIZE_PRIMARIES = `${SUBJ_SUMMARY} dataSizePrimaries`; const SUBJ_SUMMARY_DOCUMENT_COUNT = `${SUBJ_SUMMARY} documentCount`; diff --git a/x-pack/test/functional/services/monitoring/elasticsearch_indices.js b/x-pack/test/functional/services/monitoring/elasticsearch_indices.js index 1fd69293a80551..a57c5883dd8e22 100644 --- a/x-pack/test/functional/services/monitoring/elasticsearch_indices.js +++ b/x-pack/test/functional/services/monitoring/elasticsearch_indices.js @@ -13,13 +13,13 @@ export function MonitoringElasticsearchIndicesProvider({ getService, getPageObje const SUBJ_LISTING_PAGE = 'elasticsearchIndicesListingPage'; - const SUBJ_TABLE_CONTAINER = 'indicesTableContainer'; + const SUBJ_TABLE_CONTAINER = 'elasticsearchIndicesTableContainer'; const SUBJ_TABLE_NO_DATA = `${SUBJ_TABLE_CONTAINER} monitoringTableNoData`; const SUBJ_SEARCH_BAR = `${SUBJ_TABLE_CONTAINER} monitoringTableToolBar`; const SUBJ_TABLE_SORT_SEARCH_COL = `${SUBJ_TABLE_CONTAINER} tableHeaderCell-searchRate`; - const SUBJ_TABLE_BODY = 'indicesTableBody'; + const SUBJ_TABLE_BODY = 'elasticsearchIndicesTableBody'; const SUBJ_INDICES_NAMES = `${SUBJ_TABLE_BODY} name`; const SUBJ_INDICES_STATUSES = `${SUBJ_TABLE_BODY} statusIcon`; const SUBJ_INDICES_DOCUMENT_COUNTS = `${SUBJ_TABLE_BODY} documentCount`; diff --git a/x-pack/test/functional/services/monitoring/elasticsearch_node_detail.js b/x-pack/test/functional/services/monitoring/elasticsearch_node_detail.js index 7bae4ac9a3286e..007bbf61fa68f4 100644 --- a/x-pack/test/functional/services/monitoring/elasticsearch_node_detail.js +++ b/x-pack/test/functional/services/monitoring/elasticsearch_node_detail.js @@ -7,7 +7,7 @@ export function MonitoringElasticsearchNodeDetailProvider({ getService }) { const testSubjects = getService('testSubjects'); - const SUBJ_SUMMARY = 'elasticsearchNodeSummaryStatus'; + const SUBJ_SUMMARY = 'elasticsearchNodeDetailStatus'; const SUBJ_SUMMARY_TRANSPORT_ADDRESS = `${SUBJ_SUMMARY} transportAddress`; const SUBJ_SUMMARY_JVM_HEAP = `${SUBJ_SUMMARY} jvmHeap`; const SUBJ_SUMMARY_FREE_DISK_SPACE = `${SUBJ_SUMMARY} freeDiskSpace`; diff --git a/x-pack/test/functional/services/monitoring/elasticsearch_nodes.js b/x-pack/test/functional/services/monitoring/elasticsearch_nodes.js index 552b68e0b17aae..78b4773e98c39c 100644 --- a/x-pack/test/functional/services/monitoring/elasticsearch_nodes.js +++ b/x-pack/test/functional/services/monitoring/elasticsearch_nodes.js @@ -9,7 +9,7 @@ export function MonitoringElasticsearchNodesProvider({ getService/*, getPageObje const retry = getService('retry'); const SUBJ_LISTING_PAGE = 'elasticsearchNodesListingPage'; - const SUBJ_TABLE_BODY = 'nodesTableBody'; + const SUBJ_TABLE_BODY = 'elasticsearchNodesTableBody'; const SUBJ_NODE_LINK_PREFIX = `${SUBJ_TABLE_BODY} nodeLink-`; return new class ElasticsearchIndices { diff --git a/x-pack/test/functional/services/monitoring/elasticsearch_summary_status.js b/x-pack/test/functional/services/monitoring/elasticsearch_summary_status.js index 3b6d1227f665c2..930d100b74ad5d 100644 --- a/x-pack/test/functional/services/monitoring/elasticsearch_summary_status.js +++ b/x-pack/test/functional/services/monitoring/elasticsearch_summary_status.js @@ -7,7 +7,7 @@ export function MonitoringElasticsearchSummaryStatusProvider({ getService }) { const testSubjects = getService('testSubjects'); - const SUBJ_SUMMARY = 'elasticsearchSummaryStatus'; + const SUBJ_SUMMARY = 'elasticsearchClusterStatus'; const SUBJ_SUMMARY_NODES_COUNT = `${SUBJ_SUMMARY} nodesCount`; const SUBJ_SUMMARY_INDICES_COUNT = `${SUBJ_SUMMARY} indicesCount`; const SUBJ_SUMMARY_MEMORY = `${SUBJ_SUMMARY} memory`; diff --git a/x-pack/test/functional/services/monitoring/kibana_instance.js b/x-pack/test/functional/services/monitoring/kibana_instance.js index 2b43de3bb5ce04..718482ea32cb7f 100644 --- a/x-pack/test/functional/services/monitoring/kibana_instance.js +++ b/x-pack/test/functional/services/monitoring/kibana_instance.js @@ -10,7 +10,7 @@ export function MonitoringKibanaInstanceProvider({ getService }) { const SUBJ_INSTANCE_PAGE = 'kibanaInstancePage'; - const SUBJ_SUMMARY = 'kibanaInstanceStatus'; + const SUBJ_SUMMARY = 'kibanaDetailStatus'; const SUBJ_SUMMARY_TRANSPORT_ADDRESS = `${SUBJ_SUMMARY} transportAddress`; const SUBJ_SUMMARY_OS_FREE_MEMORY = `${SUBJ_SUMMARY} osFreeMemory`; const SUBJ_SUMMARY_VERSION = `${SUBJ_SUMMARY} version`; diff --git a/x-pack/test/functional/services/monitoring/kibana_summary_status.js b/x-pack/test/functional/services/monitoring/kibana_summary_status.js index de92050bf1078a..37ea0339cde0d4 100644 --- a/x-pack/test/functional/services/monitoring/kibana_summary_status.js +++ b/x-pack/test/functional/services/monitoring/kibana_summary_status.js @@ -7,7 +7,7 @@ export function MonitoringKibanaSummaryStatusProvider({ getService }) { const testSubjects = getService('testSubjects'); - const SUBJ_SUMMARY = 'kibanaSummaryStatus'; + const SUBJ_SUMMARY = 'kibanaClusterStatus'; const SUBJ_SUMMARY_INSTANCES = `${SUBJ_SUMMARY} instances`; const SUBJ_SUMMARY_MEMORY = `${SUBJ_SUMMARY} memory`; const SUBJ_SUMMARY_REQUESTS = `${SUBJ_SUMMARY} requests`; diff --git a/x-pack/test/functional/services/monitoring/logstash_summary_status.js b/x-pack/test/functional/services/monitoring/logstash_summary_status.js index 56f1eab80329a4..276413504097a3 100644 --- a/x-pack/test/functional/services/monitoring/logstash_summary_status.js +++ b/x-pack/test/functional/services/monitoring/logstash_summary_status.js @@ -7,7 +7,7 @@ export function MonitoringLogstashSummaryStatusProvider({ getService }) { const testSubjects = getService('testSubjects'); - const SUBJ_SUMMARY = 'logstashSummaryStatus'; + const SUBJ_SUMMARY = 'logstashClusterStatus'; const SUBJ_SUMMARY_NODE_COUNT = `${SUBJ_SUMMARY} node_count`; const SUBJ_SUMMARY_MEMORY_USED = `${SUBJ_SUMMARY} memory_used`; const SUBJ_SUMMARY_EVENTS_IN_TOTAL = `${SUBJ_SUMMARY} events_in_total`; diff --git a/x-pack/test/saml_api_integration/config.js b/x-pack/test/saml_api_integration/config.js index 4fade431c0c986..a278c28ace2b7f 100644 --- a/x-pack/test/saml_api_integration/config.js +++ b/x-pack/test/saml_api_integration/config.js @@ -4,13 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resolveKibanaPath } from '@kbn/plugin-helpers/lib/index'; +import { resolve } from 'path'; export default async function ({ readConfigFile }) { - // Read the Kibana API integration tests config file so that we can utilize its services. - const kibanaAPITestsConfig = await readConfigFile(resolveKibanaPath('test/api_integration/config.js')); + const kibanaAPITestsConfig = await readConfigFile(require.resolve('../../../test/api_integration/config.js')); const xPackAPITestsConfig = await readConfigFile(require.resolve('../api_integration/config.js')); + const kibanaPort = xPackAPITestsConfig.get('servers.kibana.port'); + const idpPath = resolve(__dirname, '../../test/saml_api_integration/fixtures/idp_metadata.xml'); + return { testFiles: [require.resolve('./apis')], servers: xPackAPITestsConfig.get('servers'), @@ -21,5 +23,33 @@ export default async function ({ readConfigFile }) { junit: { reportName: 'X-Pack SAML API Integration Tests', }, + env: xPackAPITestsConfig.get('env'), + + esTestCluster: { + ...xPackAPITestsConfig.get('esTestCluster'), + serverArgs: [ + ...xPackAPITestsConfig.get('esTestCluster.serverArgs'), + 'xpack.security.authc.token.enabled=true', + 'xpack.security.authc.token.timeout=15s', + 'xpack.security.authc.realms.saml1.type=saml', + 'xpack.security.authc.realms.saml1.order=0', + `xpack.security.authc.realms.saml1.idp.metadata.path=${idpPath}`, + 'xpack.security.authc.realms.saml1.idp.entity_id=http://www.elastic.co', + `xpack.security.authc.realms.saml1.sp.entity_id=http://localhost:${kibanaPort}`, + `xpack.security.authc.realms.saml1.sp.logout=http://localhost:${kibanaPort}/logout`, + `xpack.security.authc.realms.saml1.sp.acs=http://localhost:${kibanaPort}/api/security/v1/saml`, + 'xpack.security.authc.realms.saml1.attributes.principal=urn:oid:0.0.7', + ], + }, + + kbnTestServer: { + ...xPackAPITestsConfig.get('kbnTestServer'), + serverArgs: [ + ...xPackAPITestsConfig.get('kbnTestServer.serverArgs'), + '--optimize.enabled=false', + '--server.xsrf.whitelist=[\"/api/security/v1/saml\"]', + '--xpack.security.authProviders=[\"saml\"]', + ], + }, }; } diff --git a/x-pack/test/saml_api_integration/fixtures/saml_tools.js b/x-pack/test/saml_api_integration/fixtures/saml_tools.js index 74cfd8abf22e46..c9ce9bbaafbe1e 100644 --- a/x-pack/test/saml_api_integration/fixtures/saml_tools.js +++ b/x-pack/test/saml_api_integration/fixtures/saml_tools.js @@ -12,7 +12,6 @@ import zlib from 'zlib'; import { promisify } from 'bluebird'; import { parseString } from 'xml2js'; import { SignedXml } from 'xml-crypto'; -import { resolveKibanaPath } from '@kbn/plugin-helpers'; /** * @file Defines a set of tools that allow us to parse and generate various SAML XML messages. @@ -25,7 +24,7 @@ const inflateRawAsync = promisify(zlib.inflateRaw); const deflateRawAsync = promisify(zlib.deflateRaw); const parseStringAsync = promisify(parseString); -const signingKey = fs.readFileSync(resolveKibanaPath('test/dev_certs/server.key')); +const signingKey = fs.readFileSync(require.resolve('../../../../test/dev_certs/server.key')); const signatureAlgorithm = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'; export async function getSAMLRequestId(urlWithSAMLRequestId) { diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json new file mode 100644 index 00000000000000..a01f0127c96cb1 --- /dev/null +++ b/x-pack/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.json", + "include": [ + "common/**/*", + "server/**/*", + "plugins/**/*" + ] +} diff --git a/x-pack/tslint.yaml b/x-pack/tslint.yaml new file mode 100644 index 00000000000000..7fa4624642069f --- /dev/null +++ b/x-pack/tslint.yaml @@ -0,0 +1,11 @@ +extends: ../tslint.yaml + +rules: + require-license-header: + - true + - |- + /* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ diff --git a/x-pack/yarn.lock b/x-pack/yarn.lock index 6a76f5d7f6b019..79ec20fc1280b4 100644 --- a/x-pack/yarn.lock +++ b/x-pack/yarn.lock @@ -10,28 +10,25 @@ esutils "^2.0.2" js-tokens "^3.0.0" -"@elastic/eui@0.0.38": - version "0.0.38" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.38.tgz#83d55b7ad111c0a917dee2747247bac9f0be7fb5" +"@elastic/eui@0.0.49": + version "0.0.49" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.49.tgz#583b3c1526df352b99a6cf13bd750d6d5adfb949" dependencies: brace "^0.10.0" classnames "^2.2.5" core-js "^2.5.1" - eslint-config-prettier "^2.9.0" - eslint-plugin-prettier "^2.6.0" focus-trap-react "^3.0.4" highlight.js "^9.12.0" html "^1.0.0" - jquery "^3.2.1" keymirror "^0.1.1" lodash "^3.10.1" numeral "^2.0.6" - prettier "^1.11.1" prop-types "^15.6.0" react-ace "^5.5.0" react-color "^2.13.8" + react-datepicker v1.4.1 react-input-autosize "^2.2.1" - serve "^6.3.1" + react-virtualized "^9.18.5" tabbable "^1.1.0" uuid "^3.1.0" @@ -49,13 +46,6 @@ version "2.3.2" resolved "https://registry.yarnpkg.com/@elastic/numeral/-/numeral-2.3.2.tgz#06c9ef22f18dd8c2b39ffe353868d4d0c13ea4f9" -"@gulp-sourcemaps/map-sources@1.X": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz#890ae7c5d8c877f6d384860215ace9d7ec945bda" - dependencies: - normalize-path "^2.0.1" - through2 "^2.0.3" - "@kbn/datemath@link:../packages/kbn-datemath": version "0.0.0" uid "" @@ -64,29 +54,135 @@ version "0.0.0" uid "" +"@kbn/es@link:../packages/kbn-es": + version "0.0.0" + uid "" + "@kbn/plugin-helpers@link:../packages/kbn-plugin-helpers": version "0.0.0" uid "" +"@kbn/test@link:../packages/kbn-test": + version "0.0.0" + uid "" + "@kbn/ui-framework@link:../packages/kbn-ui-framework": version "0.0.0" uid "" +"@sindresorhus/is@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" + +"@sinonjs/formatio@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" + dependencies: + samsam "1.3.0" + +"@slack/client@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@slack/client/-/client-4.2.2.tgz#f997f39780bbff9c2128816e8377230a5f6bd0d5" + dependencies: + "@types/delay" "^2.0.1" + "@types/form-data" "^2.2.1" + "@types/got" "^7.1.7" + "@types/is-stream" "^1.1.0" + "@types/loglevel" "^1.5.3" + "@types/node" "^9.4.7" + "@types/p-cancelable" "^0.3.0" + "@types/p-queue" "^2.3.1" + "@types/p-retry" "^1.0.1" + "@types/retry" "^0.10.2" + "@types/url-join" "^0.8.2" + "@types/ws" "^4.0.1" + delay "^2.0.0" + eventemitter3 "^3.0.0" + finity "^0.5.4" + form-data "^2.3.1" + got "^8.0.3" + is-stream "^1.1.0" + loglevel "^1.6.1" + object.entries "^1.0.4" + object.getownpropertydescriptors "^2.0.3" + object.values "^1.0.4" + p-cancelable "^0.3.0" + p-queue "^2.3.0" + p-retry "^1.0.0" + retry "^0.10.1" + url-join "^4.0.0" + ws "^4.1.0" + +"@types/delay@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/delay/-/delay-2.0.1.tgz#61bcf318a74b61e79d1658fbf054f984c90ef901" + +"@types/events@*": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" + +"@types/form-data@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-2.2.1.tgz#ee2b3b8eaa11c0938289953606b745b738c54b1e" + dependencies: + "@types/node" "*" + +"@types/got@^7.1.7": + version "7.1.8" + resolved "https://registry.yarnpkg.com/@types/got/-/got-7.1.8.tgz#c5f421b25770689bf8948b1241f710d71a00d7dd" + dependencies: + "@types/node" "*" + +"@types/is-stream@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/is-stream/-/is-stream-1.1.0.tgz#b84d7bb207a210f2af9bed431dc0fbe9c4143be1" + dependencies: + "@types/node" "*" + "@types/jest@^22.2.3": version "22.2.3" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-22.2.3.tgz#0157c0316dc3722c43a7b71de3fdf3acbccef10d" +"@types/loglevel@^1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@types/loglevel/-/loglevel-1.5.3.tgz#adfce55383edc5998a2170ad581b3e23d6adb5b8" + "@types/node@*": version "9.3.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-9.3.0.tgz#3a129cda7c4e5df2409702626892cb4b96546dd5" -"@zeit/check-updates@1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@zeit/check-updates/-/check-updates-1.0.5.tgz#3ac40afe270a0cc646a279b629698a77ad4543c6" +"@types/node@^9.4.7": + version "9.6.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.18.tgz#092e13ef64c47e986802c9c45a61c1454813b31d" + +"@types/p-cancelable@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@types/p-cancelable/-/p-cancelable-0.3.0.tgz#3e4fcc54a3dfd81d0f5b93546bb68d0df50553bb" + +"@types/p-queue@^2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@types/p-queue/-/p-queue-2.3.1.tgz#2fb251e46e884e31c4bd1bf58f0e188972353ff4" + +"@types/p-retry@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/p-retry/-/p-retry-1.0.1.tgz#2302bc3da425014208c8a9b68293d37325124785" + dependencies: + "@types/retry" "*" + +"@types/retry@*", "@types/retry@^0.10.2": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.10.2.tgz#bd1740c4ad51966609b058803ee6874577848b37" + +"@types/url-join@^0.8.2": + version "0.8.2" + resolved "https://registry.yarnpkg.com/@types/url-join/-/url-join-0.8.2.tgz#1181ecbe1d97b7034e0ea1e35e62e86cc26b422d" + +"@types/ws@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-4.0.2.tgz#b29037627dd7ba31ec49a4f1584840422efb856f" dependencies: - chalk "^2.3.0" - ms "^2.1.1" - update-notifier "^2.3.0" + "@types/events" "*" + "@types/node" "*" abab@^1.0.3, abab@^1.0.4: version "1.0.4" @@ -103,23 +199,12 @@ accept@2.x.x: boom "5.x.x" hoek "4.x.x" -accepts@~1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" - dependencies: - mime-types "~2.1.16" - negotiator "0.6.1" - acorn-globals@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538" dependencies: acorn "^5.0.0" -acorn@4.X: - version "4.0.13" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" - acorn@^5.0.0, acorn@^5.1.2: version "5.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822" @@ -128,14 +213,16 @@ add-event-listener@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/add-event-listener/-/add-event-listener-0.0.1.tgz#a76229ebc64c8aefae204a16273a2f255abea2d0" -address@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" - agentkeepalive@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef" +agentkeepalive@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.4.1.tgz#aa95aebc3a749bca5ed53e3880a09f5235b48f0c" + dependencies: + humanize-ms "^1.2.1" + ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" @@ -191,12 +278,6 @@ angular-ui-bootstrap@1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/angular-ui-bootstrap/-/angular-ui-bootstrap-1.2.5.tgz#b0c1eff0bf3b7a65668984a1b81820a90dc60995" -ansi-align@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" - dependencies: - string-width "^2.0.0" - ansi-cyan@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" @@ -282,10 +363,6 @@ aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" -arch@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.0.tgz#3613aa46149064b3c1f0607919bf1d4786e82889" - archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" @@ -310,16 +387,6 @@ argparse@~0.1.15: underscore "~1.7.0" underscore.string "~2.4.0" -args@3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/args/-/args-3.0.8.tgz#2f425ab639c69d74ff728f3d7c6e93b97b91af7c" - dependencies: - camelcase "4.1.0" - chalk "2.1.0" - mri "1.1.0" - pkginfo "0.4.1" - string-similarity "1.2.0" - argv-split@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argv-split/-/argv-split-2.0.1.tgz#be264117790dbd5ccd63ec3f449a1804814ac4c5" @@ -439,6 +506,10 @@ astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + async@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/async/-/async-2.4.0.tgz#4990200f18ea5b837c2cc4f8c031a6985c385611" @@ -954,12 +1025,6 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -basic-auth@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.0.tgz#015db3f353e02e56377755f962742e8981e7bbba" - dependencies: - safe-buffer "5.1.1" - bcrypt-pbkdf@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" @@ -986,7 +1051,7 @@ bluebird@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.1.1.tgz#7e2e4318d62ae72a674f6aea6357bb4def1a6e41" -bluebird@3.5.1, bluebird@^3.3.1: +bluebird@^3.3.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -1024,18 +1089,6 @@ boom@5.x.x: dependencies: hoek "4.x.x" -boxen@1.3.0, boxen@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" - dependencies: - ansi-align "^2.0.0" - camelcase "^4.0.0" - chalk "^2.0.1" - cli-boxes "^1.0.0" - string-width "^2.0.0" - term-size "^1.2.0" - widest-line "^2.0.0" - brace-expansion@^1.0.0, brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -1102,9 +1155,9 @@ browser-resolve@^1.11.2, browser-resolve@^1.8.1: dependencies: resolve "1.1.7" -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" browserify-optional@^1.0.0: version "1.0.1" @@ -1151,10 +1204,6 @@ builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -1169,6 +1218,18 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cacheable-request@^2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" + dependencies: + clone-response "1.0.2" + get-stream "3.0.0" + http-cache-semantics "3.8.1" + keyv "3.0.0" + lowercase-keys "1.0.0" + normalize-url "2.0.1" + responselike "1.0.2" + call@3.x.x: version "3.0.4" resolved "https://registry.yarnpkg.com/call/-/call-3.0.4.tgz#e380f2f2a491330aa79085355f8be080877d559e" @@ -1187,10 +1248,6 @@ camelcase-keys@^2.0.0: camelcase "^2.0.0" map-obj "^1.0.0" -camelcase@4.1.0, camelcase@^4.0.0, camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" @@ -1203,9 +1260,9 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" -capture-stack-trace@^1.0.0: - version "1.0.0" - resolved "http://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" caseless@~0.12.0: version "0.12.0" @@ -1239,15 +1296,17 @@ chai@~1.9.2: assertion-error "1.0.0" deep-eql "0.1.3" -chalk@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" +chalk@^1.0.0, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" -chalk@2.3.0, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" dependencies: @@ -1255,15 +1314,13 @@ chalk@2.3.0, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" -chalk@^1.0.0, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" +chalk@^2.3.1, chalk@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" chalk@^2.3.2: version "2.3.2" @@ -1294,6 +1351,10 @@ cheerio@^1.0.0-rc.2: lodash "^4.15.0" parse5 "^3.0.1" +chownr@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + chrome-remote-interface@0.24.2: version "0.24.2" resolved "https://registry.yarnpkg.com/chrome-remote-interface/-/chrome-remote-interface-0.24.2.tgz#43a05440a1fa60b73769e72f3e7892ac11d66eba" @@ -1315,14 +1376,10 @@ class-utils@^0.3.5: lazy-cache "^2.0.2" static-extend "^0.1.1" -classnames@2.2.5, classnames@^2.1.2, classnames@^2.2.4, classnames@^2.2.5: +classnames@2.2.5, classnames@^2.1.2, classnames@^2.2.3, classnames@^2.2.4, classnames@^2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" -cli-boxes@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" - cli-cursor@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" @@ -1341,13 +1398,6 @@ clipboard@^1.6.1: select "^1.1.2" tiny-emitter "^2.0.0" -clipboardy@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.2.tgz#2ce320b9ed9be1514f79878b53ff9765420903e2" - dependencies: - arch "^2.1.0" - execa "^0.8.0" - cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -1376,6 +1426,12 @@ clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" +clone-response@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + dependencies: + mimic-response "^1.0.0" + clone-stats@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" @@ -1451,10 +1507,6 @@ commander@2.1.x: version "2.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" -commander@2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - commander@2.12.2, commander@^2.9.0: version "2.12.2" resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" @@ -1463,28 +1515,16 @@ commander@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + component-emitter@^1.2.0, component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" -compressible@~2.0.11: - version "2.0.12" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.12.tgz#c59a5c99db76767e9876500e271ef63b3493bd66" - dependencies: - mime-db ">= 1.30.0 < 2" - -compression@^1.6.2: - version "1.7.1" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.1.tgz#eff2603efc2e22cf86f35d2eb93589f9875373db" - dependencies: - accepts "~1.3.4" - bytes "3.0.0" - compressible "~2.0.11" - debug "2.6.9" - on-headers "~1.0.1" - safe-buffer "5.1.1" - vary "~1.1.2" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1513,17 +1553,6 @@ concat-stream@^1.4.7, concat-stream@~1.6.0: readable-stream "^2.2.2" typedarray "^0.0.6" -configstore@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90" - dependencies: - dot-prop "^4.1.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - unique-string "^1.0.0" - write-file-atomic "^2.0.0" - xdg-basedir "^3.0.0" - console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" @@ -1532,17 +1561,13 @@ content-type-parser@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7" -content-type@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - content@3.x.x: version "3.0.6" resolved "https://registry.yarnpkg.com/content/-/content-3.0.6.tgz#9c2e301e9ae515ed65a4b877d78aa5659bb1b809" dependencies: boom "5.x.x" -convert-source-map@1.X, convert-source-map@^1.4.0, convert-source-map@^1.5.0: +convert-source-map@^1.4.0, convert-source-map@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" @@ -1558,20 +1583,18 @@ core-js@^1.0.0: version "1.2.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" -core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.1: +core-js@^2.4.0, core-js@^2.5.0: version "2.5.3" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" +core-js@^2.5.1: + version "2.5.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.5.tgz#b14dde936c640c0579a6b50cabcc132dd6127e3b" + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -create-error-class@^3.0.0: - version "3.0.2" - resolved "http://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" - dependencies: - capture-stack-trace "^1.0.0" - create-react-class@^15.5.2: version "15.6.2" resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.2.tgz#cf1ed15f12aad7f14ef5f2dfe05e6c42f91ef02a" @@ -1580,13 +1603,6 @@ create-react-class@^15.5.2: loose-envify "^1.3.1" object-assign "^4.1.1" -create-thenable@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/create-thenable/-/create-thenable-1.0.2.tgz#e2031720ccc9575d8cfa31f5c146e762a80c0534" - dependencies: - object.omit "~2.0.0" - unique-concat "~0.2.2" - cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -1617,10 +1633,6 @@ cryptiles@3.x.x: dependencies: boom "5.x.x" -crypto-random-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - css-color-keywords@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" @@ -1646,7 +1658,7 @@ css-what@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" -css@2.X, css@^2.2.1: +css@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc" dependencies: @@ -1813,10 +1825,6 @@ d3@3.5.6: version "3.5.6" resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.6.tgz#9451c651ca733fb9672c81fb7f2655164a73a42d" -dargs@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dargs/-/dargs-5.1.0.tgz#ec7ea50c78564cd36c9d5ec18f66329fade27829" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -1834,14 +1842,6 @@ dateformat@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" -debug-fabulous@0.0.X: - version "0.0.4" - resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-0.0.4.tgz#fa071c5d87484685424807421ca4b16b0b1a0763" - dependencies: - debug "2.X" - lazy-debug-legacy "0.0.X" - object-assign "4.1.0" - debug@0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" @@ -1852,13 +1852,19 @@ debug@2.2.0: dependencies: ms "0.7.1" -debug@2.6.9, debug@2.X, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8: +debug@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b" + dependencies: + ms "0.7.2" + +debug@^2.2.0, debug@^2.3.3, debug@^2.6.8: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -debug@3.1.0, debug@^3.1.0: +debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: @@ -1872,6 +1878,12 @@ decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + dependencies: + mimic-response "^1.0.0" + dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -1949,6 +1961,12 @@ del@^2.2.2: pinkie-promise "^2.0.0" rimraf "^2.2.8" +delay@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/delay/-/delay-2.0.0.tgz#9112eadc03e4ec7e00297337896f273bbd91fae5" + dependencies: + p-defer "^1.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -1961,18 +1979,10 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" -depd@1.1.1, depd@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" - deprecated@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" @@ -1987,17 +1997,10 @@ detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" -detect-newline@2.X, detect-newline@^2.1.0: +detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" -detect-port@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.2.2.tgz#57a44533632d8bc74ad255676866ca43f96c7469" - dependencies: - address "^1.0.1" - debug "^2.6.0" - dfa@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/dfa/-/dfa-1.1.0.tgz#d30218bd10d030fa421df3ebbc82285463a31781" @@ -2008,7 +2011,11 @@ diff@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" -diff@3.5.0: +diff@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + +diff@^3.1.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -2020,6 +2027,10 @@ discontinuous-range@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" +"dom-helpers@^2.4.0 || ^3.0.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6" + dom-serializer@0, dom-serializer@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" @@ -2063,12 +2074,6 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" -dot-prop@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - dependencies: - is-obj "^1.0.0" - dotenv@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-2.0.0.tgz#bd759c357aaa70365e01c96b7b0bec08a6e0d949" @@ -2087,15 +2092,6 @@ duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" -duplexify@^3.2.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd" - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - duplexify@^3.5.3: version "3.5.4" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4" @@ -2115,10 +2111,6 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - elasticsearch@13.0.1: version "13.0.1" resolved "https://registry.yarnpkg.com/elasticsearch/-/elasticsearch-13.0.1.tgz#fa58204233052c4cd221e8721e48f3906b385b32" @@ -2130,9 +2122,16 @@ elasticsearch@13.0.1: lodash.isempty "^4.4.0" lodash.trimend "^4.5.1" -encodeurl@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" +elasticsearch@^14.1.0: + version "14.2.2" + resolved "https://registry.yarnpkg.com/elasticsearch/-/elasticsearch-14.2.2.tgz#6bbb63b19b17fa97211b22eeacb0f91197f4d6b6" + dependencies: + agentkeepalive "^3.4.1" + chalk "^1.0.0" + lodash "2.4.2" + lodash.get "^4.4.2" + lodash.isempty "^4.4.0" + lodash.trimend "^4.5.1" encoding@^0.1.11: version "0.1.12" @@ -2156,7 +2155,7 @@ entities@^1.1.1, entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" -enzyme-adapter-react-16@^1.1.0: +enzyme-adapter-react-16@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.1.1.tgz#a8f4278b47e082fbca14f5bfb1ee50ee650717b4" dependencies: @@ -2226,10 +2225,6 @@ es6-promise@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-2.0.1.tgz#ccc4963e679f0ca9fb187c777b9e583d3c7573c2" -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - escape-string-regexp@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" @@ -2278,19 +2273,6 @@ escodegen@~1.3.2: optionalDependencies: source-map "~0.1.33" -eslint-config-prettier@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3" - dependencies: - get-stdin "^5.0.1" - -eslint-plugin-prettier@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7" - dependencies: - fast-diff "^1.1.1" - jest-docblock "^21.0.0" - esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -2327,9 +2309,9 @@ esutils@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" +eventemitter3@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" exec-sh@^0.2.0: version "0.2.1" @@ -2361,18 +2343,6 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" @@ -2514,10 +2484,6 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" -fast-diff@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" - fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -2550,14 +2516,6 @@ fd-slicer@~1.0.1: dependencies: pend "~1.2.0" -fetch-mock@5.13.1: - version "5.13.1" - resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-5.13.1.tgz#955794a77f3d972f1644b9ace65a0fdfd60f1df7" - dependencies: - glob-to-regexp "^0.3.0" - node-fetch "^1.3.3" - path-to-regexp "^1.7.0" - figures@^1.3.5: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -2576,10 +2534,6 @@ fileset@^2.0.2: glob "^7.0.3" minimatch "^3.0.3" -filesize@3.5.11: - version "3.5.11" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.11.tgz#1919326749433bb3cf77368bd158caabcc19e9ee" - fill-keys@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20" @@ -2648,6 +2602,10 @@ fined@^1.0.1: object.pick "^1.2.0" parse-filepath "^1.0.1" +finity@^0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/finity/-/finity-0.5.4.tgz#f2a8a9198e8286467328ec32c8bfcc19a2229c11" + first-chunk-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" @@ -2663,13 +2621,7 @@ flush-write-stream@^1.0.2: inherits "^2.0.1" readable-stream "^2.0.4" -focus-trap-react@^3.0.4: - version "3.1.1" - resolved "https://registry.yarnpkg.com/focus-trap-react/-/focus-trap-react-3.1.1.tgz#d8cad66e01de2ae05686eae8942f4008fdd19e53" - dependencies: - focus-trap "^2.0.1" - -focus-trap-react@^3.1.1: +focus-trap-react@^3.0.4, focus-trap-react@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/focus-trap-react/-/focus-trap-react-3.1.2.tgz#4dd021ccd028bbd3321147d132cdf7585d6d1394" dependencies: @@ -2747,12 +2699,6 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" -formatio@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" - dependencies: - samsam "~1.1" - formidable@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.1.1.tgz#96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9" @@ -2763,22 +2709,17 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" +from2@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" from@^0.1.3: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" -fs-extra@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-mkdirp-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" @@ -2865,11 +2806,7 @@ get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" -get-stdin@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" - -get-stream@^3.0.0: +get-stream@3.0.0, get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -2877,6 +2814,10 @@ get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" +getopts@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.0.6.tgz#4788d533a977527e79efd57b5e742ffa0dd33105" + getos@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/getos/-/getos-3.1.0.tgz#db3aa4df15a3295557ce5e81aa9e3e5cdfaa6567" @@ -2902,7 +2843,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob-parent@^3.0.0, glob-parent@^3.1.0: +glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" dependencies: @@ -2920,19 +2861,6 @@ glob-stream@^3.1.5: through2 "^0.6.1" unique-stream "^1.0.0" -glob-stream@^5.2.0: - version "5.3.5" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - glob-stream@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" @@ -2948,10 +2876,6 @@ glob-stream@^6.1.0: to-absolute-glob "^2.0.0" unique-stream "^2.0.2" -glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - glob-watcher@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b" @@ -2981,14 +2905,14 @@ glob@6.0.4, glob@^6.0.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.1.2, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" +glob@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.0.2" once "^1.3.0" path-is-absolute "^1.0.0" @@ -3001,13 +2925,14 @@ glob@^4.3.1: minimatch "^2.0.1" once "^1.3.0" -glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" +glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: + fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "2 || 3" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" @@ -3028,12 +2953,6 @@ glob@~4.3.0: minimatch "^2.0.1" once "^1.3.0" -global-dirs@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - dependencies: - ini "^1.3.4" - global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -3105,25 +3024,27 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" -got@^6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" +got@^8.0.3: + version "8.3.1" + resolved "https://registry.yarnpkg.com/got/-/got-8.3.1.tgz#093324403d4d955f5a16a7a8d39955d055ae10ed" dependencies: - create-error-class "^3.0.0" + "@sindresorhus/is" "^0.7.0" + cacheable-request "^2.1.1" + decompress-response "^3.3.0" duplexer3 "^0.1.4" get-stream "^3.0.0" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" + into-stream "^3.1.0" + is-retry-allowed "^1.1.0" + isurl "^1.0.0-alpha5" lowercase-keys "^1.0.0" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - unzip-response "^2.0.1" - url-parse-lax "^1.0.0" - -graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + mimic-response "^1.0.0" + p-cancelable "^0.4.0" + p-timeout "^2.0.1" + pify "^3.0.0" + safe-buffer "^5.1.1" + timed-out "^4.0.1" + url-parse-lax "^3.0.0" + url-to-options "^1.0.1" graceful-fs@^3.0.0: version "3.0.11" @@ -3131,10 +3052,18 @@ graceful-fs@^3.0.0: dependencies: natives "^1.1.0" +graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + graceful-fs@~1.2.0: version "1.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + graphlib-dot@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/graphlib-dot/-/graphlib-dot-0.6.2.tgz#872e933d0bb349430cb813a2491943d1c5f1e952" @@ -3148,10 +3077,6 @@ graphlib@^1.0.1: dependencies: lodash "^3.10.0" -growl@1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - growl@1.9.2: version "1.9.2" resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" @@ -3184,22 +3109,6 @@ gulp-rename@1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.2.2.tgz#3ad4428763f05e2764dec1c67d868db275687817" -gulp-sourcemaps@^1.5.2: - version "1.12.0" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.12.0.tgz#786f97c94a0f968492465d70558e04242c679598" - dependencies: - "@gulp-sourcemaps/map-sources" "1.X" - acorn "4.X" - convert-source-map "1.X" - css "2.X" - debug-fabulous "0.0.X" - detect-newline "2.X" - graceful-fs "4.X" - source-map "0.X" - strip-bom "2.X" - through2 "2.X" - vinyl "1.X" - gulp-util@3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.7.tgz#78925c4b8f8b49005ac01a011c557e6218941cbb" @@ -3290,7 +3199,7 @@ gulplog@^1.0.0: dependencies: glogg "^1.0.0" -handlebars@4.0.11, handlebars@^4.0.3: +handlebars@^4.0.3: version "4.0.11" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" dependencies: @@ -3378,10 +3287,20 @@ has-gulplog@^0.1.0: dependencies: sparkles "^1.0.0" +has-symbol-support-x@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" + has-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" +has-to-string-tag-x@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + dependencies: + has-symbol-support-x "^1.4.1" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -3443,10 +3362,6 @@ hawk@~6.0.2: hoek "4.x.x" sntp "2.x.x" -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - heavy@4.x.x: version "4.0.4" resolved "https://registry.yarnpkg.com/heavy/-/heavy-4.0.4.tgz#36c91336c00ccfe852caa4d153086335cd2f00e9" @@ -3529,14 +3444,9 @@ htmlparser2@^3.9.1: inherits "^2.0.1" readable-stream "^2.0.2" -http-errors@1.6.2, http-errors@~1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" - dependencies: - depd "1.1.1" - inherits "2.0.3" - setprototypeof "1.0.3" - statuses ">= 1.3.1 < 2" +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" http-errors@~1.4.0: version "1.4.0" @@ -3561,6 +3471,12 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + dependencies: + ms "^2.0.0" + humps@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/humps/-/humps-2.0.1.tgz#dd02ea6081bd0568dc5d073184463957ba9ef9aa" @@ -3583,10 +3499,6 @@ immutability-helper@^2.0.0: dependencies: invariant "^2.2.0" -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - import-local@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" @@ -3615,7 +3527,7 @@ inherits@1: version "1.0.2" resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -3650,6 +3562,13 @@ interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" +into-stream@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" + dependencies: + from2 "^2.1.1" + p-is-promise "^1.1.0" + invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" @@ -3660,10 +3579,6 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" -ip@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - iron@4.x.x: version "4.0.5" resolved "https://registry.yarnpkg.com/iron/-/iron-4.0.5.tgz#4f042cceb8b9738f346b59aa734c83a89bc31428" @@ -3811,21 +3726,10 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-installed-globally@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" - dependencies: - global-dirs "^0.1.0" - is-path-inside "^1.0.0" - is-negated-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" -is-npm@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" - is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -3838,11 +3742,7 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - -is-object@~1.0.1: +is-object@^1.0.1, is-object@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" @@ -3868,6 +3768,10 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -3886,10 +3790,6 @@ is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" -is-redirect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" - is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" @@ -3902,11 +3802,11 @@ is-relative@^1.0.0: dependencies: is-unc-path "^1.0.0" -is-retry-allowed@^1.0.0: +is-retry-allowed@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" -is-stream@1.1.0, is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -3932,10 +3832,6 @@ is-utf8@^0.2.0, is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - is-valid-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" @@ -3944,10 +3840,6 @@ is-windows@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -4052,6 +3944,13 @@ istanbul-reports@^1.1.3: dependencies: handlebars "^4.0.3" +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + items@2.x.x: version "2.1.1" resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198" @@ -4137,10 +4036,6 @@ jest-diff@^22.4.3: jest-get-type "^22.4.3" pretty-format "^22.4.3" -jest-docblock@^21.0.0: - version "21.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" - jest-docblock@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-22.4.3.tgz#50886f132b42b280c903c592373bb6e93bb68b19" @@ -4373,7 +4268,7 @@ joi@9.x.x: moment "2.x.x" topo "2.x.x" -jquery@^3.1.1, jquery@^3.2.1: +jquery@^3.1.1: version "3.2.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.2.1.tgz#5c4d9de652af6cd0a770154a631bba12b015c787" @@ -4433,6 +4328,10 @@ jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" @@ -4451,16 +4350,14 @@ json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - optionalDependencies: - graceful-fs "^4.1.6" - jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -4478,10 +4375,20 @@ jstimezonedetect@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/jstimezonedetect/-/jstimezonedetect-1.0.5.tgz#93d035cd20e8c7d64eb1375cf5aa7a10a024466a" +just-extend@^1.1.27: + version "1.1.27" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" + keymirror@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/keymirror/-/keymirror-0.1.1.tgz#918889ea13f8d0a42e7c557250eee713adc95c35" +keyv@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" + dependencies: + json-buffer "3.0.0" + kilt@2.x.x: version "2.0.2" resolved "https://registry.yarnpkg.com/kilt/-/kilt-2.0.2.tgz#04d7183c298a1232efddf7ddca5959a8f6301e20" @@ -4512,12 +4419,6 @@ kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" -latest-version@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" - dependencies: - package-json "^4.0.0" - lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" @@ -4528,10 +4429,6 @@ lazy-cache@^2.0.2: dependencies: set-getter "^0.1.0" -lazy-debug-legacy@0.0.X: - version "0.0.1" - resolved "https://registry.yarnpkg.com/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz#537716c0776e4cf79e3ed1b621f7658c2911b1b1" - lazystream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" @@ -4607,6 +4504,13 @@ lodash-es@^4.17.4, lodash-es@^4.2.0, lodash-es@^4.2.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7" +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + lodash._basecallback@^3.0.0: version "3.3.1" resolved "https://registry.yarnpkg.com/lodash._basecallback/-/lodash._basecallback-3.3.1.tgz#b7b2bb43dc2160424a21ccf26c57e443772a8e27" @@ -4624,6 +4528,10 @@ lodash._basecopy@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + lodash._baseeach@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash._baseeach/-/lodash._baseeach-3.0.4.tgz#cf8706572ca144e8d9d75227c990da982f932af3" @@ -4682,6 +4590,14 @@ lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash.debounce@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-3.1.1.tgz#812211c378a94cc29d5aa4e3346cf0bfce3a7df5" @@ -4718,7 +4634,7 @@ lodash.isempty@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" -lodash.isequal@^4.1.1: +lodash.isequal@^4.1.1, lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -4829,15 +4745,19 @@ lodash@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" -lolex@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" +loglevel@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" + +lolex@^2.2.0, lolex@^2.3.2: + version "2.6.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.6.0.tgz#cf9166f3c9dece3cdeb5d6b01fce50f14a1203e3" longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.0, loose-envify@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" dependencies: @@ -4850,10 +4770,14 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" -lowercase-keys@^1.0.0: +lowercase-keys@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" +lowercase-keys@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + lowlight@~1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.9.1.tgz#ed7c3dffc36f8c1f263735c0fe0c907847c11250" @@ -4871,12 +4795,6 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" -make-dir@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51" - dependencies: - pify "^3.0.0" - make-iterator@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.0.tgz#57bef5dc85d23923ba23767324d8e8f8f3d9694b" @@ -4932,7 +4850,7 @@ merge-descriptors@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" -merge-stream@^1.0.0, merge-stream@^1.0.1: +merge-stream@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" dependencies: @@ -4946,22 +4864,7 @@ methods@^1.1.1, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" -micro-compress@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micro-compress/-/micro-compress-1.0.0.tgz#53f5a80b4ad0320ca165a559b6e3df145d4f704f" - dependencies: - compression "^1.6.2" - -micro@9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/micro/-/micro-9.1.0.tgz#f2effba306639076e994c007c327dfc36a5185e9" - dependencies: - content-type "1.0.4" - is-stream "1.1.0" - mri "1.1.0" - raw-body "2.3.2" - -micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7: +micromatch@^2.1.5, micromatch@^2.3.11: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" dependencies: @@ -4997,7 +4900,7 @@ micromatch@^3.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -mime-db@1.x.x, "mime-db@>= 1.30.0 < 2": +mime-db@1.x.x: version "1.32.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414" @@ -5005,16 +4908,12 @@ mime-db@~1.30.0: version "1.30.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" -mime-types@2.1.17, mime-types@^2.1.12, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.7: +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: mime-db "~1.30.0" -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - mime@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -5023,6 +4922,10 @@ mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" +mimic-response@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" + mimos@3.x.x: version "3.0.3" resolved "https://registry.yarnpkg.com/mimos/-/mimos-3.0.3.tgz#b9109072ad378c2b72f6a0101c43ddfb2b36641f" @@ -5097,6 +5000,22 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: dependencies: minimist "0.0.8" +mocha@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.3.0.tgz#d29b7428d3f52c82e2e65df1ecb7064e1aabbfb5" + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.6.0" + diff "3.2.0" + escape-string-regexp "1.0.5" + glob "7.1.1" + growl "1.9.2" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + mocha@^2.0.1: version "2.5.3" resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" @@ -5112,21 +5031,6 @@ mocha@^2.0.1: supports-color "1.2.0" to-iso-string "0.0.2" -mocha@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.5.tgz#e228e3386b9387a4710007a641f127b00be44b52" - dependencies: - browser-stdout "1.3.1" - commander "2.11.0" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.3" - he "1.1.1" - mkdirp "0.5.1" - supports-color "4.4.0" - module-not-found-error@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/module-not-found-error/-/module-not-found-error-1.0.1.tgz#cf8b4ff4f29640674d6cdd02b0e3bc523c2bbdc0" @@ -5145,19 +5049,19 @@ moment@2.x.x, "moment@>= 2.9.0", moment@^2.13.0, moment@^2.20.1: version "2.20.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd" -mri@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.0.tgz#5c0a3f29c8ccffbbb1ec941dcec09d71fa32f36a" - ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -ms@^2.1.1: +ms@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" @@ -5175,6 +5079,10 @@ multipipe@^0.1.2: dependencies: duplexer2 "0.0.2" +mustache@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0" + mute-stream@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db" @@ -5199,10 +5107,6 @@ nanomatch@^1.2.5: snapdragon "^0.8.1" to-regex "^3.0.1" -native-promise-only@~0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" - natives@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.1.tgz#011acce1f7cbd87f7ba6b3093d6cd9392be1c574" @@ -5219,10 +5123,6 @@ nearley@^2.7.10: railroad-diagrams "^1.0.0" randexp "^0.4.2" -negotiator@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - ngreact@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/ngreact/-/ngreact-0.5.1.tgz#2dcccc1541771796689d13e51bb8d5010af41c57" @@ -5238,14 +5138,24 @@ nigel@2.x.x: hoek "4.x.x" vise "2.x.x" -node-fetch@^1.0.1, node-fetch@^1.3.3: +nise@^1.2.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.3.3.tgz#c17a850066a8a1dfeb37f921da02441afc4a82ba" + dependencies: + "@sinonjs/formatio" "^2.0.0" + just-extend "^1.1.27" + lolex "^2.3.2" + path-to-regexp "^1.7.0" + text-encoding "^0.6.4" + +node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" dependencies: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.1.2: +node-fetch@^2.0.0, node-fetch@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" @@ -5278,9 +5188,9 @@ node-pre-gyp@^0.6.39: tar "^2.2.1" tar-pack "^3.4.0" -node-version@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.1.0.tgz#f437d7ba407e65e2c4eaef8887b1718ba523d4f0" +nodemailer@^4.6.4: + version "4.6.4" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-4.6.4.tgz#f0d72d0c6a6ec5f4369fa8f4bf5127a31baa2014" nomnom@~1.6.2: version "1.6.2" @@ -5311,6 +5221,14 @@ normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1: dependencies: remove-trailing-separator "^1.0.1" +normalize-url@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" + dependencies: + prepend-http "^2.0.0" + query-string "^5.0.1" + sort-keys "^2.0.0" + now-and-later@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.0.tgz#bc61cbb456d79cb32207ce47ca05136ff2e7d6ee" @@ -5354,15 +5272,11 @@ oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" -object-assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - object-assign@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" -object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -5441,7 +5355,7 @@ object.map@^1.0.0: for-own "^1.0.0" make-iterator "^1.0.0" -object.omit@^2.0.0, object.omit@~2.0.0: +object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" dependencies: @@ -5463,16 +5377,6 @@ object.values@^1.0.4: function-bind "^1.1.0" has "^1.0.1" -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" - once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -5489,16 +5393,6 @@ onetime@^1.0.0: version "1.1.0" resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" -openssl-self-signed-certificate@1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/openssl-self-signed-certificate/-/openssl-self-signed-certificate-1.1.6.tgz#9d3a4776b1a57e9847350392114ad2f915a83dd4" - -opn@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519" - dependencies: - is-wsl "^1.1.0" - optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -5535,13 +5429,6 @@ ordered-read-streams@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz#fd565a9af8eb4473ba69b6ed8a34352cb552f126" -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - ordered-read-streams@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" @@ -5570,7 +5457,7 @@ os-shim@^0.1.2: version "0.1.3" resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -5581,10 +5468,26 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + +p-cancelable@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" +p-is-promise@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" + p-limit@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" @@ -5597,18 +5500,25 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" -p-try@^1.0.0: +p-queue@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-2.4.2.tgz#03609826682b743be9a22dba25051bd46724fc34" + +p-retry@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-1.0.0.tgz#3927332a4b7d70269b535515117fc547da1a6968" + dependencies: + retry "^0.10.0" -package-json@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" +p-timeout@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" dependencies: - got "^6.7.1" - registry-auth-token "^3.0.1" - registry-url "^3.0.3" - semver "^5.1.0" + p-finally "^1.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" pako@^0.2.5: version "0.2.9" @@ -5704,12 +5614,6 @@ path-to-regexp@^1.0.0, path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" -path-type@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - dependencies: - pify "^3.0.0" - path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -5828,10 +5732,6 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" -pkginfo@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" - plugin-error@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" @@ -5864,6 +5764,10 @@ pngjs@3.3.1, pngjs@^3.0.0: version "3.3.1" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.1.tgz#8e14e6679ee7424b544334c3b2d21cea6d8c209a" +popper.js@^1.14.1: + version "1.14.3" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -5876,18 +5780,14 @@ prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -prettier@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.1.tgz#61e43fc4cd44e68f2b0dfc2c38cd4bb0fccdcc75" - pretty-format@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-22.4.3.tgz#f873d780839a9c02e9664c8a082e9ee79eaac16f" @@ -5939,6 +5839,14 @@ prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, loose-envify "^1.3.1" object-assign "^4.1.1" +prop-types@^15.6.1: + version "15.6.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.3.1" + object-assign "^4.1.1" + proxyquire@1.7.11: version "1.7.11" resolved "https://registry.yarnpkg.com/proxyquire/-/proxyquire-1.7.11.tgz#13b494eb1e71fb21cc3ebe3699e637d3bec1af9e" @@ -6013,6 +5921,14 @@ qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + quote-stream@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2" @@ -6052,20 +5968,7 @@ randomatic@^1.1.3: is-number "^3.0.0" kind-of "^4.0.0" -range-parser@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - -raw-body@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" - dependencies: - bytes "3.0.0" - http-errors "1.6.2" - iconv-lite "0.4.19" - unpipe "1.0.0" - -rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: +rc@^1.1.7: version "1.2.3" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.3.tgz#51575a900f8dd68381c710b4712c2154c3e2035b" dependencies: @@ -6074,7 +5977,16 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-ace@^5.5.0, react-ace@^5.9.0: +react-ace@^5.5.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-5.10.0.tgz#e328b37ac52759f700be5afdb86ada2f5ec84c5e" + dependencies: + brace "^0.11.0" + lodash.get "^4.4.2" + lodash.isequal "^4.1.1" + prop-types "^15.5.8" + +react-ace@^5.9.0: version "5.9.0" resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-5.9.0.tgz#427a1cc4869b960a6f9748aa7eb169a9269fc336" dependencies: @@ -6107,7 +6019,16 @@ react-color@^2.13.8: reactcss "^1.2.0" tinycolor2 "^1.4.1" -react-dom@^16.0.0, react-dom@^16.2.0: +react-datepicker@v1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-1.4.1.tgz#ee171b71d9853e56f9eece5fc3186402f4648683" + dependencies: + classnames "^2.2.5" + prop-types "^15.6.0" + react-onclickoutside "^6.7.1" + react-popper "^0.9.1" + +react-dom@^16.0.0: version "16.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" dependencies: @@ -6116,6 +6037,15 @@ react-dom@^16.0.0, react-dom@^16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" +react-dom@^16.3.0: + version "16.3.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.3.2.tgz#cb90f107e09536d683d84ed5d4888e9640e0e4df" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.0" + react-input-autosize@^2.1.2, react-input-autosize@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8" @@ -6138,6 +6068,17 @@ react-motion@^0.4.8: prop-types "^15.5.8" raf "^3.1.0" +react-onclickoutside@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.7.1.tgz#6a5b5b8b4eae6b776259712c89c8a2b36b17be93" + +react-popper@^0.9.1: + version "0.9.5" + resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-0.9.5.tgz#02a24ef3eec33af9e54e8358ab70eb0e331edd05" + dependencies: + popper.js "^1.14.1" + prop-types "^15.6.1" + react-portal@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-3.2.0.tgz#4224e19b2b05d5cbe730a7ba0e34ec7585de0043" @@ -6153,6 +6094,14 @@ react-reconciler@^0.7.0: object-assign "^4.1.1" prop-types "^15.6.0" +react-redux-request@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/react-redux-request/-/react-redux-request-1.5.5.tgz#693562b0d85293d9d16b02e13ea13f118950bb1d" + dependencies: + lodash.get "^4.4.2" + lodash.isequal "^4.5.0" + prop-types "^15.6.1" + react-redux@^5.0.5: version "5.0.6" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.6.tgz#23ed3a4f986359d68b5212eaaa681e60d6574946" @@ -6222,6 +6171,16 @@ react-test-renderer@^16.0.0-0, react-test-renderer@^16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" +react-virtualized@^9.18.5: + version "9.18.5" + resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.18.5.tgz#42dd390ebaa7ea809bfcaf775d39872641679b89" + dependencies: + babel-runtime "^6.26.0" + classnames "^2.2.3" + dom-helpers "^2.4.0 || ^3.0.0" + loose-envify "^1.3.0" + prop-types "^15.6.0" + react-vis@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/react-vis/-/react-vis-1.8.2.tgz#0e0aebc427e50856a01b666569ffad0411ef050f" @@ -6252,6 +6211,15 @@ react@>=0.13.3, react@^16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" +react@^16.3.0: + version "16.3.2" + resolved "https://registry.yarnpkg.com/react/-/react-16.3.2.tgz#fdc8420398533a1e58872f59091b272ce2f91ea9" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.0" + reactcss@^1.2.0: version "1.2.3" resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd" @@ -6411,19 +6379,6 @@ regexpu-core@^2.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -registry-auth-token@^3.0.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006" - dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" - -registry-url@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - dependencies: - rc "^1.0.1" - regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" @@ -6634,6 +6589,12 @@ resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7: dependencies: path-parse "^1.0.5" +responselike@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + dependencies: + lowercase-keys "^1.0.0" + restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -6651,6 +6612,10 @@ ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" +retry@^0.10.0, retry@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" @@ -6706,17 +6671,19 @@ rxjs@5.3.0: dependencies: symbol-observable "^1.0.1" -safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +rxjs@^5.4.3: + version "5.5.10" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.10.tgz#fde02d7a614f6c8683d0d1957827f492e09db045" + dependencies: + symbol-observable "1.0.1" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -samsam@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" - -samsam@~1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621" +samsam@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" sane@^2.0.0: version "2.2.0" @@ -6752,13 +6719,7 @@ select@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" -semver-diff@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" - dependencies: - semver "^5.0.3" - -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -6774,54 +6735,10 @@ semver@^5.4.1, semver@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" -send@0.16.1: - version "0.16.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" - dependencies: - debug "2.6.9" - depd "~1.1.1" - destroy "~1.0.4" - encodeurl "~1.0.1" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.3.1" - sequencify@~0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" -serve@^6.3.1: - version "6.4.8" - resolved "https://registry.yarnpkg.com/serve/-/serve-6.4.8.tgz#6057b2f04eadf8d8c0cec9a301592e670808672b" - dependencies: - "@zeit/check-updates" "1.0.5" - args "3.0.8" - basic-auth "2.0.0" - bluebird "3.5.1" - boxen "1.3.0" - chalk "2.3.0" - clipboardy "1.2.2" - dargs "5.1.0" - detect-port "1.2.2" - filesize "3.5.11" - fs-extra "5.0.0" - handlebars "4.0.11" - ip "1.1.5" - micro "9.1.0" - micro-compress "1.0.0" - mime-types "2.1.17" - node-version "1.1.0" - openssl-self-signed-certificate "1.1.6" - opn "5.1.0" - path-type "3.0.0" - send "0.16.1" - set-blocking@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-1.0.0.tgz#cd5e5d938048df1ac92dfe92e1f16add656f5ec5" @@ -6858,10 +6775,6 @@ setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" -setprototypeof@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" - shallow-copy@~0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" @@ -6895,25 +6808,27 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -simple-git@1.32.1: - version "1.32.1" - resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.32.1.tgz#d51ef8832717a73a27917d4f91c3dfbf01ff275f" +simple-git@1.37.0: + version "1.37.0" + resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.37.0.tgz#a5d522dd4e97c6091f657766c28a323738233f0f" -sinon-as-promised@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/sinon-as-promised/-/sinon-as-promised-4.0.3.tgz#c0545b1685fd813588a4ed697012487ed11d151b" +simple-git@^1.91.0: + version "1.92.0" + resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.92.0.tgz#6061468eb7d19f0141078fc742e62457e910f547" dependencies: - create-thenable "~1.0.0" - native-promise-only "~0.8.1" + debug "^3.1.0" -sinon@1.17.3: - version "1.17.3" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.3.tgz#44d64bc748d023880046c1543cefcea34c47d17e" +sinon@^5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-5.0.7.tgz#3bded6a73613ccc9e512e20246ced69a27c27dab" dependencies: - formatio "1.1.1" - lolex "1.3.2" - samsam "1.1.2" - util ">=0.10.3 <1" + "@sinonjs/formatio" "^2.0.0" + diff "^3.1.0" + lodash.get "^4.4.2" + lolex "^2.2.0" + nise "^1.2.0" + supports-color "^5.1.0" + type-detect "^4.0.5" slash@^1.0.0: version "1.0.0" @@ -6958,6 +6873,12 @@ sntp@2.x.x: dependencies: hoek "4.x.x" +sort-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" + dependencies: + is-plain-obj "^1.0.0" + source-map-resolve@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761" @@ -6997,7 +6918,7 @@ source-map-url@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" -source-map@0.X, "source-map@>= 0.1.2", source-map@^0.6.0: +"source-map@>= 0.1.2", source-map@^0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -7110,14 +7031,10 @@ static-module@^1.1.0: static-eval "~0.2.0" through2 "~0.4.1" -"statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2": +"statuses@>= 1.2.1 < 2": version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" -statuses@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" - stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" @@ -7136,6 +7053,10 @@ stream-to-observable@0.2.0: dependencies: any-observable "^0.2.0" +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + string-length@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" @@ -7143,12 +7064,6 @@ string-length@^2.0.0: astral-regex "^1.0.0" strip-ansi "^4.0.0" -string-similarity@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-1.2.0.tgz#d75153cb383846318b7a39a8d9292bb4db4e9c30" - dependencies: - lodash "^4.13.1" - string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -7190,19 +7105,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" - -strip-bom@2.X, strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - dependencies: - is-utf8 "^0.2.0" - strip-bom@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -7214,6 +7116,12 @@ strip-bom@^1.0.0: first-chunk-stream "^1.0.0" is-utf8 "^0.2.0" +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -7288,11 +7196,11 @@ supports-color@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" -supports-color@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" +supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" dependencies: - has-flag "^2.0.0" + has-flag "^1.0.0" supports-color@^2.0.0: version "2.0.0" @@ -7310,12 +7218,22 @@ supports-color@^4.0.0: dependencies: has-flag "^2.0.0" +supports-color@^5.1.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + supports-color@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" dependencies: has-flag "^3.0.0" +symbol-observable@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" + symbol-observable@^1.0.1, symbol-observable@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.1.0.tgz#5c68fd8d54115d9dfb72a84720549222e8db9b32" @@ -7344,6 +7262,24 @@ tar-fs@1.13.0: pump "^1.0.0" tar-stream "^1.1.2" +tar-fs@^1.16.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.0.tgz#e877a25acbcc51d8c790da1c57c9cf439817b896" + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-fs@^1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.2.tgz#17e5239747e399f7e77344f5f53365f04af53577" + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + tar-pack@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" @@ -7381,12 +7317,6 @@ temp@^0.8.3: os-tmpdir "^1.0.0" rimraf "~2.2.6" -term-size@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" - dependencies: - execa "^0.7.0" - test-exclude@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" @@ -7401,6 +7331,10 @@ tether@^1.3.7: version "1.4.3" resolved "https://registry.yarnpkg.com/tether/-/tether-1.4.3.tgz#fd547024c47b6e5c9b87e1880f997991a9a6ad54" +text-encoding@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" @@ -7419,20 +7353,20 @@ through2-map@^3.0.0: through2 "~2.0.0" xtend "^4.0.0" -through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through2@^0.6.0, through2@^0.6.1: +through2@^0.6.1: version "0.6.5" resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" dependencies: readable-stream ">=1.0.33-1 <1.1.0-0" xtend ">=4.0.0 <4.1.0-0" +through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + through2@~0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" @@ -7454,7 +7388,7 @@ time-stamp@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" -timed-out@^4.0.0: +timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" @@ -7486,16 +7420,16 @@ tmp@^0.0.29: dependencies: os-tmpdir "~1.0.1" +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + dependencies: + os-tmpdir "~1.0.2" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - dependencies: - extend-shallow "^2.0.1" - to-absolute-glob@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" @@ -7600,10 +7534,18 @@ type-detect@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" +type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + typedarray@^0.0.6, typedarray@~0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" +typescript@^2.8.3: + version "2.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170" + ua-parser-js@^0.7.9: version "0.7.17" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" @@ -7679,10 +7621,6 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^0.4.3" -unique-concat@~0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/unique-concat/-/unique-concat-0.2.2.tgz#9210f9bdcaacc5e1e3929490d7c019df96f18712" - unique-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" @@ -7694,20 +7632,6 @@ unique-stream@^2.0.2: json-stable-stringify "^1.0.0" through2-filter "^2.0.0" -unique-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - dependencies: - crypto-random-string "^1.0.0" - -universalify@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" - -unpipe@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -7715,33 +7639,23 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -unzip-response@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" - -update-notifier@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451" - dependencies: - boxen "^1.2.1" - chalk "^2.0.1" - configstore "^3.0.0" - import-lazy "^2.1.0" - is-installed-globally "^0.1.0" - is-npm "^1.0.0" - latest-version "^3.0.0" - semver-diff "^2.0.0" - xdg-basedir "^3.0.0" - urix@^0.1.0, urix@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" +url-join@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.0.tgz#4d3340e807d3773bda9991f8305acdcc2a665d2a" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" dependencies: - prepend-http "^1.0.1" + prepend-http "^2.0.0" + +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" use@^2.0.0: version "2.0.2" @@ -7766,12 +7680,6 @@ util.promisify@^1.0.0: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" -"util@>=0.10.3 <1": - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - dependencies: - inherits "2.0.1" - uuid@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" @@ -7801,10 +7709,6 @@ value-or-function@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - venn.js@0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/venn.js/-/venn.js-0.2.9.tgz#33c29075efa484731d59d884752900cc33033656" @@ -7817,26 +7721,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vinyl-fs@2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.3.1.tgz#f6aebb3987ec300791be324389d6bb7d8ce8537b" - dependencies: - duplexify "^3.2.0" - glob-stream "^5.2.0" - graceful-fs "^4.0.0" - gulp-sourcemaps "^1.5.2" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vinyl "^1.0.0" - vinyl-fs@^0.3.0: version "0.3.14" resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6" @@ -7872,6 +7756,28 @@ vinyl-fs@^3.0.0: vinyl "^2.0.0" vinyl-sourcemap "^1.1.0" +vinyl-fs@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" + dependencies: + fs-mkdirp-stream "^1.0.0" + glob-stream "^6.1.0" + graceful-fs "^4.0.0" + is-valid-glob "^1.0.0" + lazystream "^1.0.0" + lead "^1.0.0" + object.assign "^4.0.4" + pumpify "^1.3.5" + readable-stream "^2.3.3" + remove-bom-buffer "^3.0.0" + remove-bom-stream "^1.2.0" + resolve-options "^1.1.0" + through2 "^2.0.0" + to-through "^2.0.0" + value-or-function "^3.0.0" + vinyl "^2.0.0" + vinyl-sourcemap "^1.1.0" + vinyl-sourcemap@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" @@ -7884,14 +7790,6 @@ vinyl-sourcemap@^1.1.0: remove-bom-buffer "^3.0.0" vinyl "^2.0.0" -vinyl@1.X, vinyl@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - vinyl@^0.4.0: version "0.4.6" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" @@ -8003,12 +7901,6 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2" -widest-line@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.0.tgz#0142a4e8a243f8882c0233aa0e0281aa76152273" - dependencies: - string-width "^2.1.1" - window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" @@ -8047,7 +7939,7 @@ wreck@12.x.x: boom "5.x.x" hoek "4.x.x" -write-file-atomic@^2.0.0, write-file-atomic@^2.1.0: +write-file-atomic@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" dependencies: @@ -8061,9 +7953,12 @@ ws@2.0.x: dependencies: ultron "~1.1.0" -xdg-basedir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" +ws@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" xml-crypto@^0.10.1: version "0.10.1" @@ -8195,3 +8090,7 @@ yazl@^2.1.0: resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.4.3.tgz#ec26e5cc87d5601b9df8432dbdd3cd2e5173a071" dependencies: buffer-crc32 "~0.2.3" + +zlib@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/zlib/-/zlib-1.0.5.tgz#6e7c972fc371c645a6afb03ab14769def114fcc0" diff --git a/yarn.lock b/yarn.lock index e6265dd48917ee..4463c1787138ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -77,28 +77,25 @@ version "0.0.0" uid "" -"@elastic/eui@0.0.38", "@elastic/eui@v0.0.38": - version "0.0.38" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.38.tgz#83d55b7ad111c0a917dee2747247bac9f0be7fb5" +"@elastic/eui@0.0.49", "@elastic/eui@v0.0.49": + version "0.0.49" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.49.tgz#583b3c1526df352b99a6cf13bd750d6d5adfb949" dependencies: brace "^0.10.0" classnames "^2.2.5" core-js "^2.5.1" - eslint-config-prettier "^2.9.0" - eslint-plugin-prettier "^2.6.0" focus-trap-react "^3.0.4" highlight.js "^9.12.0" html "^1.0.0" - jquery "^3.2.1" keymirror "^0.1.1" lodash "^3.10.1" numeral "^2.0.6" - prettier "^1.11.1" prop-types "^15.6.0" react-ace "^5.5.0" react-color "^2.13.8" + react-datepicker v1.4.1 react-input-autosize "^2.2.1" - serve "^6.3.1" + react-virtualized "^9.18.5" tabbable "^1.1.0" uuid "^3.1.0" @@ -160,6 +157,10 @@ version "0.0.0" uid "" +"@kbn/test@link:packages/kbn-test": + version "0.0.0" + uid "" + "@kbn/ui-framework@link:packages/kbn-ui-framework": version "0.0.0" uid "" @@ -171,21 +172,185 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@samverschueren/stream-to-observable@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" + dependencies: + any-observable "^0.3.0" + +"@sindresorhus/is@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" + +"@sinonjs/formatio@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" + dependencies: + samsam "1.3.0" + +"@slack/client@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@slack/client/-/client-4.2.2.tgz#f997f39780bbff9c2128816e8377230a5f6bd0d5" + dependencies: + "@types/delay" "^2.0.1" + "@types/form-data" "^2.2.1" + "@types/got" "^7.1.7" + "@types/is-stream" "^1.1.0" + "@types/loglevel" "^1.5.3" + "@types/node" "^9.4.7" + "@types/p-cancelable" "^0.3.0" + "@types/p-queue" "^2.3.1" + "@types/p-retry" "^1.0.1" + "@types/retry" "^0.10.2" + "@types/url-join" "^0.8.2" + "@types/ws" "^4.0.1" + delay "^2.0.0" + eventemitter3 "^3.0.0" + finity "^0.5.4" + form-data "^2.3.1" + got "^8.0.3" + is-stream "^1.1.0" + loglevel "^1.6.1" + object.entries "^1.0.4" + object.getownpropertydescriptors "^2.0.3" + object.values "^1.0.4" + p-cancelable "^0.3.0" + p-queue "^2.3.0" + p-retry "^1.0.0" + retry "^0.10.1" + url-join "^4.0.0" + ws "^4.1.0" + +"@types/delay@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/delay/-/delay-2.0.1.tgz#61bcf318a74b61e79d1658fbf054f984c90ef901" + +"@types/eslint@^4.16.2": + version "4.16.2" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-4.16.2.tgz#30f4f026019eb78a6ef12f276b75cd16ea2afb27" + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + +"@types/events@*": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" + +"@types/execa@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@types/execa/-/execa-0.9.0.tgz#9b025d2755f17e80beaf9368c3f4f319d8b0fb93" + dependencies: + "@types/node" "*" + +"@types/form-data@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-2.2.1.tgz#ee2b3b8eaa11c0938289953606b745b738c54b1e" + dependencies: + "@types/node" "*" + +"@types/getopts@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/getopts/-/getopts-2.0.0.tgz#8a603370cb367d3192bd8012ad39ab2320b5b476" + +"@types/glob@^5.0.35": + version "5.0.35" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.35.tgz#1ae151c802cece940443b5ac246925c85189f32a" + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/got@^7.1.7": + version "7.1.8" + resolved "https://registry.yarnpkg.com/@types/got/-/got-7.1.8.tgz#c5f421b25770689bf8948b1241f710d71a00d7dd" + dependencies: + "@types/node" "*" + +"@types/is-stream@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/is-stream/-/is-stream-1.1.0.tgz#b84d7bb207a210f2af9bed431dc0fbe9c4143be1" + dependencies: + "@types/node" "*" + +"@types/json-schema@*": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-6.0.1.tgz#a761975746f1c1b2579c62e3a4b5e88f986f7e2e" + "@types/json-stable-stringify@^1.0.32": version "1.0.32" resolved "https://registry.yarnpkg.com/@types/json-stable-stringify/-/json-stable-stringify-1.0.32.tgz#121f6917c4389db3923640b2e68de5fa64dda88e" +"@types/listr@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@types/listr/-/listr-0.13.0.tgz#6250bc4a04123cafa24fc73d1b880653a6ae6721" + dependencies: + "@types/node" "*" + +"@types/loglevel@^1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@types/loglevel/-/loglevel-1.5.3.tgz#adfce55383edc5998a2170ad581b3e23d6adb5b8" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + +"@types/minimatch@^2.0.29": + version "2.0.29" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a" + "@types/node@*": version "9.4.7" resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.7.tgz#57d81cd98719df2c9de118f2d5f3b1120dcd7275" -"@zeit/check-updates@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@zeit/check-updates/-/check-updates-1.1.0.tgz#d0f65026a36f27cd1fd54c647d8294447c1d2d8b" +"@types/node@^9.4.7": + version "9.6.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.18.tgz#092e13ef64c47e986802c9c45a61c1454813b31d" + +"@types/p-cancelable@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@types/p-cancelable/-/p-cancelable-0.3.0.tgz#3e4fcc54a3dfd81d0f5b93546bb68d0df50553bb" + +"@types/p-queue@^2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@types/p-queue/-/p-queue-2.3.1.tgz#2fb251e46e884e31c4bd1bf58f0e188972353ff4" + +"@types/p-retry@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/p-retry/-/p-retry-1.0.1.tgz#2302bc3da425014208c8a9b68293d37325124785" + dependencies: + "@types/retry" "*" + +"@types/react-dom@^16.0.5": + version "16.0.5" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.0.5.tgz#a757457662e3819409229e8f86795ff37b371f96" + dependencies: + "@types/node" "*" + "@types/react" "*" + +"@types/react@*", "@types/react@^16.3.14": + version "16.3.14" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.3.14.tgz#f90ac6834de172e13ecca430dcb6814744225d36" + dependencies: + csstype "^2.2.0" + +"@types/retry@*", "@types/retry@^0.10.2": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.10.2.tgz#bd1740c4ad51966609b058803ee6874577848b37" + +"@types/url-join@^0.8.2": + version "0.8.2" + resolved "https://registry.yarnpkg.com/@types/url-join/-/url-join-0.8.2.tgz#1181ecbe1d97b7034e0ea1e35e62e86cc26b422d" + +"@types/ws@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-4.0.2.tgz#b29037627dd7ba31ec49a4f1584840422efb856f" dependencies: - chalk "2.3.0" - ms "2.1.1" - update-notifier "2.3.0" + "@types/events" "*" + "@types/node" "*" JSONStream@1.1.1: version "1.1.1" @@ -224,13 +389,6 @@ accepts@1.3.3: mime-types "~2.1.11" negotiator "0.6.1" -accepts@~1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - dependencies: - mime-types "~2.1.18" - negotiator "0.6.1" - acorn-dynamic-import@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" @@ -279,10 +437,6 @@ add-event-listener@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/add-event-listener/-/add-event-listener-0.0.1.tgz#a76229ebc64c8aefae204a16273a2f255abea2d0" -address@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" - adm-zip@0.4.7: version "0.4.7" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" @@ -291,14 +445,7 @@ after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" -agent-base@2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7" - dependencies: - extend "~3.0.0" - semver "~5.0.1" - -agent-base@^4.1.0: +agent-base@4, agent-base@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.0.tgz#9838b5c3392b962bad031e6a4c5e1024abec45ce" dependencies: @@ -314,10 +461,6 @@ agentkeepalive@^3.4.1: dependencies: humanize-ms "^1.2.1" -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" - ajv-keywords@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" @@ -326,7 +469,7 @@ ajv-keywords@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.1.0.tgz#ac2b27939c543e95d2c06e7f7f5c27be4aa543be" -ajv@^4.7.0, ajv@^4.9.1: +ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: @@ -439,7 +582,7 @@ ansi-colors@^1.0.1: dependencies: ansi-wrap "^0.1.0" -ansi-escapes@^1.1.0: +ansi-escapes@^1.0.0, ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -481,6 +624,10 @@ any-observable@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.2.0.tgz#c67870058003579009083f54ac0abafb5c33d242" +any-observable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" + anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" @@ -511,10 +658,6 @@ aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" -arch@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.0.tgz#3613aa46149064b3c1f0607919bf1d4786e82889" - are-we-there-yet@~1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" @@ -535,16 +678,6 @@ argparse@~0.1.15: underscore "~1.7.0" underscore.string "~2.4.0" -args@3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/args/-/args-3.0.8.tgz#2f425ab639c69d74ff728f3d7c6e93b97b91af7c" - dependencies: - camelcase "4.1.0" - chalk "2.1.0" - mri "1.1.0" - pkginfo "0.4.1" - string-similarity "1.2.0" - arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" @@ -799,7 +932,7 @@ b64@3.x.x: version "3.0.3" resolved "https://registry.yarnpkg.com/b64/-/b64-3.0.3.tgz#36afeee0d9345f046387ce6de8a6702afe5bb56e" -babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.20.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: +babel-code-frame@^6.11.0, babel-code-frame@^6.20.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -855,6 +988,30 @@ babel-core@^6.0.0, babel-core@^6.18.0, babel-core@^6.26.0: slash "^1.0.0" source-map "^0.5.6" +babel-core@^6.26.3: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + babel-eslint@8.1.2: version "8.1.2" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.1.2.tgz#a39230b0c20ecbaa19a35d5633bf9b9ca2c8116f" @@ -1019,7 +1176,7 @@ babel-plugin-check-es2015-constants@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-istanbul@^4.1.4, babel-plugin-istanbul@^4.1.5: +babel-plugin-istanbul@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.5.tgz#6760cdd977f411d3e175bb064f2bc327d99b2b6e" dependencies: @@ -1027,9 +1184,14 @@ babel-plugin-istanbul@^4.1.4, babel-plugin-istanbul@^4.1.5: istanbul-lib-instrument "^1.7.5" test-exclude "^4.1.1" -babel-plugin-jest-hoist@^22.4.1: - version "22.4.1" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.4.1.tgz#d712fe5da8b6965f3191dacddbefdbdf4fb66d63" +babel-plugin-istanbul@^4.1.6: + version "4.1.6" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.13.0" + find-up "^2.1.0" + istanbul-lib-instrument "^1.10.1" + test-exclude "^4.2.1" babel-plugin-jest-hoist@^22.4.3: version "22.4.3" @@ -1183,7 +1345,7 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1, babel-plugin-transform-es2015-modules-commonjs@^6.26.0: +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" dependencies: @@ -1192,6 +1354,15 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e babel-template "^6.26.0" babel-types "^6.26.0" +babel-plugin-transform-es2015-modules-commonjs@^6.26.2: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" @@ -1407,13 +1578,6 @@ babel-preset-flow@^6.23.0: dependencies: babel-plugin-transform-flow-strip-types "^6.22.0" -babel-preset-jest@^22.4.0: - version "22.4.1" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-22.4.1.tgz#efa2e5f5334242a9457a068452d7d09735db172a" - dependencies: - babel-plugin-jest-hoist "^22.4.1" - babel-plugin-syntax-object-rest-spread "^6.13.0" - babel-preset-jest@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-22.4.3.tgz#e92eef9813b7026ab4ca675799f37419b5a44156" @@ -1565,12 +1729,6 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -basic-auth@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.0.tgz#015db3f353e02e56377755f962742e8981e7bbba" - dependencies: - safe-buffer "5.1.1" - batch-processor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8" @@ -1627,14 +1785,14 @@ bluebird@3.4.6: version "3.4.6" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.6.tgz#01da8d821d87813d158967e743d5fe6c62cf8c0f" -bluebird@3.5.1, bluebird@^3.3.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" - -bluebird@^2.10.0, bluebird@^2.9.24: +bluebird@^2.10.0: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" +bluebird@^3.3.0, bluebird@^3.3.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + bmp-js@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.0.3.tgz#64113e9c7cf1202b376ed607bf30626ebe57b18a" @@ -1721,7 +1879,7 @@ boom@5.2.0, boom@5.x.x: dependencies: hoek "4.x.x" -boxen@1.3.0, boxen@^1.2.1, boxen@^1.2.2: +boxen@^1.2.1, boxen@^1.2.2: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" dependencies: @@ -1746,7 +1904,7 @@ brace@0.10.0, brace@^0.10.0: dependencies: w3c-blob "0.0.1" -brace@^0.11.0: +brace@0.11.1, brace@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.1.tgz#4896fcc9d544eef45f4bb7660db320d3b379fe58" @@ -1814,10 +1972,6 @@ browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.1.tgz#38b7ab55edb806ff2dcda1a7f1620773a477c49f" @@ -1909,6 +2063,10 @@ buffer-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" +buffer-from@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531" + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -2026,6 +2184,18 @@ cache-loader@1.0.3: loader-utils "^1.1.0" mkdirp "^0.5.1" +cacheable-request@^2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" + dependencies: + clone-response "1.0.2" + get-stream "3.0.0" + http-cache-semantics "3.8.1" + keyv "3.0.0" + lowercase-keys "1.0.0" + normalize-url "2.0.1" + responselike "1.0.2" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -2069,10 +2239,6 @@ camelcase-keys@^3.0.0: camelcase "^3.0.0" map-obj "^1.0.0" -camelcase@4.1.0, camelcase@^4.0.0, camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" @@ -2085,6 +2251,10 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" +camelcase@^4.0.0, camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + caniuse-api@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" @@ -2144,14 +2314,6 @@ chai@3.5.0, "chai@>=1.9.2 <4.0.0": deep-eql "^0.1.3" type-detect "^1.0.0" -chalk@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - chalk@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" @@ -2160,14 +2322,6 @@ chalk@2.3.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" -chalk@2.3.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3, chalk@~1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -2178,6 +2332,22 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3, chalk@~1.1.1: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chalk@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" @@ -2188,9 +2358,9 @@ chalk@~0.5.1: strip-ansi "^0.3.0" supports-color "^0.2.0" -chance@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.6.tgz#4734f62d02b738cdc2882d8b5d41f89af49e7bfd" +chance@1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.10.tgz#03500b04ad94e778dd2891b09ec73a6ad87b1996" character-entities-legacy@^1.0.0: version "1.1.1" @@ -2347,7 +2517,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@2.2.5, classnames@2.x, classnames@^2.1.2, classnames@^2.2.4, classnames@^2.2.5: +classnames@2.2.5, classnames@2.x, classnames@^2.1.2, classnames@^2.2.3, classnames@^2.2.4, classnames@^2.2.5: version "2.2.5" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" @@ -2362,7 +2532,7 @@ cli-boxes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" -cli-cursor@^1.0.1: +cli-cursor@^1.0.1, cli-cursor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" dependencies: @@ -2374,10 +2544,21 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-spinners@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" + cli-spinners@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.1.0.tgz#f1847b168844d917a671eb9d147e3df497c90d06" +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + dependencies: + slice-ansi "0.0.4" + string-width "^1.0.1" + cli-width@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-1.1.1.tgz#a4d293ef67ebb7b88d4a4d42c0ccf00c4d1e366d" @@ -2394,13 +2575,6 @@ clipboard@^1.6.1: select "^1.1.2" tiny-emitter "^2.0.0" -clipboardy@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef" - dependencies: - arch "^2.1.0" - execa "^0.8.0" - cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -2429,6 +2603,12 @@ clone-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" +clone-response@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + dependencies: + mimic-response "^1.0.0" + clone-stats@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" @@ -2560,7 +2740,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@2: +commander@2, commander@^2.12.1: version "2.15.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" @@ -2568,10 +2748,6 @@ commander@2.1.x: version "2.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.1.0.tgz#d121bbae860d9992a3d517ba96f56588e47c6781" -commander@2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - commander@2.8.1, commander@2.8.x, commander@~2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" @@ -2612,24 +2788,6 @@ component-inherit@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" -compressible@~2.0.13: - version "2.0.13" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9" - dependencies: - mime-db ">= 1.33.0 < 2" - -compression@^1.6.2: - version "1.7.2" - resolved "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69" - dependencies: - accepts "~1.3.4" - bytes "3.0.0" - compressible "~2.0.13" - debug "2.6.9" - on-headers "~1.0.1" - safe-buffer "5.1.1" - vary "~1.1.2" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2658,7 +2816,7 @@ concat-stream@1.6.0: readable-stream "^2.2.2" typedarray "^0.0.6" -concat-stream@^1.4.7, concat-stream@^1.5.2, concat-stream@^1.6.0, concat-stream@~1.6.0: +concat-stream@^1.4.7, concat-stream@^1.6.0, concat-stream@~1.6.0: version "1.6.1" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.1.tgz#261b8f518301f1d834e36342b9fea095d2620a26" dependencies: @@ -2744,7 +2902,7 @@ content-type-parser@^1.0.1, content-type-parser@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7" -content-type@1.0.4, content-type@~1.0.1, content-type@~1.0.4: +content-type@~1.0.1, content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -3082,6 +3240,10 @@ cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0", "cssom@>= 0.3.2 < 0.4.0": dependencies: cssom "0.3.x" +csstype@^2.2.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.5.2.tgz#4534308476ceede8fbe148b9b99f9baf1c80fa06" + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -3306,16 +3468,16 @@ d@1: dependencies: es5-ext "^0.10.9" -dargs@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dargs/-/dargs-5.1.0.tgz#ec7ea50c78564cd36c9d5ec18f66329fade27829" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" dependencies: assert-plus "^1.0.0" +date-fns@^1.27.2: + version "1.29.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" + date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" @@ -3339,12 +3501,6 @@ debug@0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" -debug@2, debug@2.6.9, debug@2.X, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - dependencies: - ms "2.0.0" - debug@2.2.0, debug@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" @@ -3363,6 +3519,12 @@ debug@2.6.0: dependencies: ms "0.7.2" +debug@2.6.9, debug@2.X, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + debug@3.1.0, debug@^3.0.1, debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -3387,6 +3549,12 @@ decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + dependencies: + mimic-response "^1.0.0" + decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" @@ -3516,6 +3684,12 @@ del@^3.0.0: pify "^3.0.0" rimraf "^2.2.8" +delay@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/delay/-/delay-2.0.0.tgz#9112eadc03e4ec7e00297337896f273bbd91fae5" + dependencies: + p-defer "^1.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -3536,7 +3710,7 @@ depd@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa" -depd@~1.1.0, depd@~1.1.1, depd@~1.1.2: +depd@~1.1.0, depd@~1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -3547,10 +3721,6 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" @@ -3565,13 +3735,6 @@ detect-newline@2.X, detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" -detect-port@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.2.2.tgz#57a44533632d8bc74ad255676866ca43f96c7469" - dependencies: - address "^1.0.1" - debug "^2.6.0" - dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -3593,7 +3756,7 @@ diff@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" -diff@3.5.0, diff@^3.2.0: +diff@^3.1.0, diff@^3.2.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -3633,6 +3796,10 @@ dojo@2.0.0-alpha.7: version "2.0.0-alpha.7" resolved "https://registry.yarnpkg.com/dojo/-/dojo-2.0.0-alpha.7.tgz#c2b25d43d8f72ccc9c8fe89a34906a2d271e5c91" +"dom-helpers@^2.4.0 || ^3.0.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6" + dom-serialize@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" @@ -3820,6 +3987,10 @@ electron-to-chromium@^1.2.7: version "1.3.39" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.39.tgz#d7a4696409ca0995e2750156da612c221afad84d" +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" + element-resize-detector@^1.1.12: version "1.1.14" resolved "https://registry.yarnpkg.com/element-resize-detector/-/element-resize-detector-1.1.14.tgz#af064a0a618a820ad570a95c5eec5b77be0128c1" @@ -3846,7 +4017,7 @@ encode-uri-query@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/encode-uri-query/-/encode-uri-query-1.0.0.tgz#d632be4aafe8316c6145007ffb2844c5312b194c" -encodeurl@~1.0.1, encodeurl@~1.0.2: +encodeurl@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -3901,7 +4072,7 @@ engine.io@1.8.3: engine.io-parser "1.3.2" ws "1.1.2" -enhanced-resolve@^3.4.0: +enhanced-resolve@^3.0.0, enhanced-resolve@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e" dependencies: @@ -3950,9 +4121,9 @@ enzyme-adapter-utils@^1.3.0: object.assign "^4.0.4" prop-types "^15.6.0" -enzyme-to-json@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.3.0.tgz#553e23a09ffb4b0cf09287e2edf9c6539fddaa84" +enzyme-to-json@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.3.1.tgz#64239dcd417e2fb552f4baa6632de4744b9b5b93" dependencies: lodash "^4.17.4" @@ -4187,17 +4358,15 @@ eslint-plugin-mocha@4.11.0: dependencies: ramda "^0.24.1" -eslint-plugin-no-unsanitized@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-2.0.2.tgz#a42a83c9b3d9386101d6fd6915c41759fa7a37f7" - dependencies: - eslint "^3.19.0" +eslint-plugin-no-unsanitized@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.0.2.tgz#83c6fcf8e34715112757e03dd4ee436dce29ed45" eslint-plugin-prefer-object-spread@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/eslint-plugin-prefer-object-spread/-/eslint-plugin-prefer-object-spread-1.2.1.tgz#27fb91853690cceb3ae6101d9c8aecc6a67a402c" -eslint-plugin-prettier@^2.6.0: +eslint-plugin-prettier@^2.2.0, eslint-plugin-prettier@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7" dependencies: @@ -4266,47 +4435,7 @@ eslint@4.14.0: table "^4.0.1" text-table "~0.2.0" -eslint@^3.19.0: - version "3.19.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" - dependencies: - babel-code-frame "^6.16.0" - chalk "^1.1.3" - concat-stream "^1.5.2" - debug "^2.1.1" - doctrine "^2.0.0" - escope "^3.6.0" - espree "^3.4.0" - esquery "^1.0.0" - estraverse "^4.2.0" - esutils "^2.0.2" - file-entry-cache "^2.0.0" - glob "^7.0.3" - globals "^9.14.0" - ignore "^3.2.0" - imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" - is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" - levn "^0.3.0" - lodash "^4.0.0" - mkdirp "^0.5.0" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.7.5" - strip-bom "^3.0.0" - strip-json-comments "~2.0.1" - table "^3.7.8" - text-table "~0.2.0" - user-home "^2.0.0" - -espree@^3.4.0, espree@^3.5.2: +espree@^3.5.2: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" dependencies: @@ -4365,10 +4494,6 @@ esutils@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - even-better@7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/even-better/-/even-better-7.0.2.tgz#d056f429c90ecc20ee9494aca0a751f743504d2e" @@ -4406,6 +4531,10 @@ eventemitter3@1.x.x: version "1.2.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" +eventemitter3@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" + events@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -4447,18 +4576,6 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.9.0.tgz#adb7ce62cf985071f60580deb4a88b9e34712d01" @@ -4526,17 +4643,6 @@ expect.js@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.3.1.tgz#b0a59a0d2eff5437544ebf0ceaa6015841d09b5b" -expect@^22.4.0: - version "22.4.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-22.4.0.tgz#371edf1ae15b83b5bf5ec34b42f1584660a36c16" - dependencies: - ansi-styles "^3.2.0" - jest-diff "^22.4.0" - jest-get-type "^22.1.0" - jest-matcher-utils "^22.4.0" - jest-message-util "^22.4.0" - jest-regex-util "^22.1.0" - expect@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/expect/-/expect-22.4.3.tgz#d5a29d0a0e1fb2153557caef2674d4547e914674" @@ -4565,7 +4671,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@3, extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: +extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -4712,7 +4818,15 @@ fd-slicer@~1.0.1: dependencies: pend "~1.2.0" -figures@^1.3.5: +fetch-mock@^5.13.1: + version "5.13.1" + resolved "https://registry.yarnpkg.com/fetch-mock/-/fetch-mock-5.13.1.tgz#955794a77f3d972f1644b9ace65a0fdfd60f1df7" + dependencies: + glob-to-regexp "^0.3.0" + node-fetch "^1.3.3" + path-to-regexp "^1.7.0" + +figures@^1.3.5, figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" dependencies: @@ -4774,10 +4888,6 @@ fileset@^2.0.2: glob "^7.0.3" minimatch "^3.0.3" -filesize@3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.0.tgz#22d079615624bb6fd3c04026120628a41b3f4efa" - fill-keys@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20" @@ -4858,6 +4968,10 @@ findup-sync@~0.3.0: dependencies: glob "~5.0.0" +finity@^0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/finity/-/finity-0.5.4.tgz#f2a8a9198e8286467328ec32c8bfcc19a2229c11" + flat-cache@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" @@ -4956,12 +5070,6 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" -formatio@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" - dependencies: - samsam "~1.1" - formidable@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.1.tgz#70fb7ca0290ee6ff961090415f4b3df3d2082659" @@ -4972,9 +5080,12 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" +from2@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" from@^0.1.3, from@~0: version "0.1.7" @@ -4990,17 +5101,9 @@ fs-exists-sync@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" -fs-extra@4.0.3, fs-extra@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" +fs-extra@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.0.tgz#0f0afb290bb3deb87978da816fcd3c7797f3a817" dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -5014,6 +5117,14 @@ fs-extra@^3.0.1: jsonfile "^3.0.0" universalify "^0.1.0" +fs-extra@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-mkdirp-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" @@ -5099,16 +5210,6 @@ geckodriver@1.11.0: got "5.6.0" tar "4.0.2" -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" @@ -5133,6 +5234,10 @@ get-stdin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" +get-stream@3.0.0, get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" @@ -5140,10 +5245,6 @@ get-stream@^2.2.0: object-assign "^4.0.1" pinkie-promise "^2.0.0" -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -5160,6 +5261,10 @@ getopts@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.0.5.tgz#e4d3948e87fd9fb50c8a0f2912f4de16301fb8ae" +getopts@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.0.6.tgz#4788d533a977527e79efd57b5e742ffa0dd33105" + getos@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/getos/-/getos-3.1.0.tgz#db3aa4df15a3295557ce5e81aa9e3e5cdfaa6567" @@ -5273,17 +5378,6 @@ glob@7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^4.0.6: version "4.5.3" resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" @@ -5303,6 +5397,17 @@ glob@^5.0.14, glob@^5.0.15, glob@~5.0.0, glob@~5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@~3.2.9: version "3.2.11" resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" @@ -5342,7 +5447,7 @@ globals@^11.0.1: version "11.3.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.3.0.tgz#e04fdb7b9796d8adac9c8f64c14837b2313378b0" -globals@^9.14.0, globals@^9.18.0: +globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -5367,7 +5472,7 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globby@^8.0.0: +globby@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50" dependencies: @@ -5460,6 +5565,28 @@ got@^6.3.0, got@^6.7.1: unzip-response "^2.0.1" url-parse-lax "^1.0.0" +got@^8.0.3: + version "8.3.1" + resolved "https://registry.yarnpkg.com/got/-/got-8.3.1.tgz#093324403d4d955f5a16a7a8d39955d055ae10ed" + dependencies: + "@sindresorhus/is" "^0.7.0" + cacheable-request "^2.1.1" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + into-stream "^3.1.0" + is-retry-allowed "^1.1.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + mimic-response "^1.0.0" + p-cancelable "^0.4.0" + p-timeout "^2.0.1" + pify "^3.0.0" + safe-buffer "^5.1.1" + timed-out "^4.0.1" + url-parse-lax "^3.0.0" + url-to-options "^1.0.1" + graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -5481,10 +5608,6 @@ graphlib@^1.0.1: dependencies: lodash "^3.10.0" -growl@1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - growl@1.9.2: version "1.9.2" resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" @@ -5571,12 +5694,6 @@ grunt-run@0.7.0: lodash "^3.10.0" strip-ansi "^3.0.0" -grunt-simple-mocha@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/grunt-simple-mocha/-/grunt-simple-mocha-0.4.0.tgz#bdf4c1b26d93cf938a875481c1786211faad7ac0" - dependencies: - mocha "*" - grunt@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/grunt/-/grunt-1.0.1.tgz#e8778764e944b18f32bb0f10b9078475c9dfb56b" @@ -5631,9 +5748,9 @@ h2o2@5.1.1: joi "9.X.X" wreck "9.X.X" -handlebars@4.0.11, handlebars@^4.0.1, handlebars@^4.0.3: - version "4.0.11" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" +handlebars@4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.5.tgz#92c6ed6bb164110c50d4d8d0fbddc70806c6f8e7" dependencies: async "^1.4.0" optimist "^0.6.1" @@ -5641,9 +5758,9 @@ handlebars@4.0.11, handlebars@^4.0.1, handlebars@^4.0.3: optionalDependencies: uglify-js "^2.6" -handlebars@4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.5.tgz#92c6ed6bb164110c50d4d8d0fbddc70806c6f8e7" +handlebars@^4.0.1, handlebars@^4.0.3: + version "4.0.11" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" dependencies: async "^1.4.0" optimist "^0.6.1" @@ -5834,10 +5951,6 @@ hawk@~6.0.2: hoek "4.x.x" sntp "2.x.x" -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - he@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/he/-/he-0.5.0.tgz#2c05ffaef90b68e860f3fd2b54ef580989277ee2" @@ -5944,6 +6057,10 @@ htmlparser2@^3.9.1: inherits "^2.0.1" readable-stream "^2.0.2" +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + http-errors@1.6.2, http-errors@~1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" @@ -5971,13 +6088,12 @@ http-parser-js@>=0.4.0: version "0.4.9" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.9.tgz#ea1a04fb64adff0242e9974f297dd4c3cad271e1" -http-proxy-agent@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-1.0.0.tgz#cc1ce38e453bf984a0f7702d2dd59c73d081284a" +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" dependencies: - agent-base "2" - debug "2" - extend "3" + agent-base "4" + debug "3.1.0" http-proxy@^1.13.0: version "1.16.2" @@ -6006,9 +6122,9 @@ https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" -https-proxy-agent@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz#a7ce4382a1ba8266ee848578778122d491260fd9" +https-proxy-agent@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" dependencies: agent-base "^4.1.0" debug "^3.1.0" @@ -6057,7 +6173,7 @@ ieee754@^1.1.4: version "1.1.10" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.10.tgz#719a6f7b026831e64bdb838b0de1bb0029bbf716" -ignore@^3.2.0, ignore@^3.3.3, ignore@^3.3.5: +ignore@^3.3.3, ignore@^3.3.5: version "3.3.7" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" @@ -6171,24 +6287,6 @@ inquirer@^0.11.1: strip-ansi "^3.0.0" through "^2.3.6" -inquirer@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" - dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" - cli-width "^2.0.0" - figures "^1.3.5" - lodash "^4.3.0" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - string-width "^1.0.1" - strip-ansi "^3.0.0" - through "^2.3.6" - inquirer@^3.0.6, inquirer@^3.2.3: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" @@ -6238,6 +6336,13 @@ interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" +into-stream@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" + dependencies: + from2 "^2.1.1" + p-is-promise "^1.1.0" + invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -6252,10 +6357,6 @@ ip-regex@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" -ip@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - iron@4.x.x: version "4.0.5" resolved "https://registry.yarnpkg.com/iron/-/iron-4.0.5.tgz#4f042cceb8b9738f346b59aa734c83a89bc31428" @@ -6466,20 +6567,6 @@ is-installed-globally@^0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" -is-my-ip-valid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - -is-my-json-valid@^2.10.0: - version "2.17.2" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" @@ -6520,6 +6607,12 @@ is-object@^1.0.1, is-object@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" +is-observable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" + dependencies: + symbol-observable "^1.1.0" + is-odd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" @@ -6568,10 +6661,6 @@ is-promise@~1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-1.0.1.tgz#31573761c057e33c2e91aab9e96da08cefbe76e5" -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" @@ -6598,11 +6687,11 @@ is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" -is-retry-allowed@^1.0.0: +is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" -is-stream@1.1.0, is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -6660,10 +6749,6 @@ is-word-character@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.1.tgz#5a03fa1ea91ace8a6eb0c7cd770eb86d65c8befb" -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -6902,22 +6987,6 @@ jest-cli@^22.4.3: which "^1.2.12" yargs "^10.0.3" -jest-config@^22.4.2: - version "22.4.2" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-22.4.2.tgz#580ba5819bf81a5e48f4fd470e8b81834f45c855" - dependencies: - chalk "^2.0.1" - glob "^7.1.1" - jest-environment-jsdom "^22.4.1" - jest-environment-node "^22.4.1" - jest-get-type "^22.1.0" - jest-jasmine2 "^22.4.2" - jest-regex-util "^22.1.0" - jest-resolve "^22.4.2" - jest-util "^22.4.1" - jest-validate "^22.4.2" - pretty-format "^22.4.0" - jest-config@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-22.4.3.tgz#0e9d57db267839ea31309119b41dc2fa31b76403" @@ -6934,15 +7003,6 @@ jest-config@^22.4.3: jest-validate "^22.4.3" pretty-format "^22.4.3" -jest-diff@^22.4.0: - version "22.4.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-22.4.0.tgz#384c2b78519ca44ca126382df53f134289232525" - dependencies: - chalk "^2.0.1" - diff "^3.2.0" - jest-get-type "^22.1.0" - pretty-format "^22.4.0" - jest-diff@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-22.4.3.tgz#e18cc3feff0aeef159d02310f2686d4065378030" @@ -6962,14 +7022,6 @@ jest-docblock@^22.4.3: dependencies: detect-newline "^2.1.0" -jest-environment-jsdom@^22.4.1: - version "22.4.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-22.4.1.tgz#754f408872441740100d3917e5ec40c74de6447f" - dependencies: - jest-mock "^22.2.0" - jest-util "^22.4.1" - jsdom "^11.5.1" - jest-environment-jsdom@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-22.4.3.tgz#d67daa4155e33516aecdd35afd82d4abf0fa8a1e" @@ -6978,13 +7030,6 @@ jest-environment-jsdom@^22.4.3: jest-util "^22.4.3" jsdom "^11.5.1" -jest-environment-node@^22.4.1: - version "22.4.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-22.4.1.tgz#418850eb654596b8d6e36c2021cbedbc23df8e16" - dependencies: - jest-mock "^22.2.0" - jest-util "^22.4.1" - jest-environment-node@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-22.4.3.tgz#54c4eaa374c83dd52a9da8759be14ebe1d0b9129" @@ -6992,10 +7037,6 @@ jest-environment-node@^22.4.3: jest-mock "^22.4.3" jest-util "^22.4.3" -jest-get-type@^22.1.0: - version "22.1.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.1.0.tgz#4e90af298ed6181edc85d2da500dbd2753e0d5a9" - jest-get-type@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" @@ -7012,22 +7053,6 @@ jest-haste-map@^22.4.3: micromatch "^2.3.11" sane "^2.0.0" -jest-jasmine2@^22.4.2: - version "22.4.2" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-22.4.2.tgz#dfd3d259579ed6f52510d8f1ab692808f0d40691" - dependencies: - chalk "^2.0.1" - co "^4.6.0" - expect "^22.4.0" - graceful-fs "^4.1.11" - is-generator-fn "^1.0.0" - jest-diff "^22.4.0" - jest-matcher-utils "^22.4.0" - jest-message-util "^22.4.0" - jest-snapshot "^22.4.0" - jest-util "^22.4.1" - source-map-support "^0.5.0" - jest-jasmine2@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-22.4.3.tgz#4daf64cd14c793da9db34a7c7b8dcfe52a745965" @@ -7050,14 +7075,6 @@ jest-leak-detector@^22.4.3: dependencies: pretty-format "^22.4.3" -jest-matcher-utils@^22.4.0: - version "22.4.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-22.4.0.tgz#d55f5faf2270462736bdf7c7485ee931c9d4b6a1" - dependencies: - chalk "^2.0.1" - jest-get-type "^22.1.0" - pretty-format "^22.4.0" - jest-matcher-utils@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-22.4.3.tgz#4632fe428ebc73ebc194d3c7b65d37b161f710ff" @@ -7066,16 +7083,6 @@ jest-matcher-utils@^22.4.3: jest-get-type "^22.4.3" pretty-format "^22.4.3" -jest-message-util@^22.4.0: - version "22.4.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-22.4.0.tgz#e3d861df16d2fee60cb2bc8feac2188a42579642" - dependencies: - "@babel/code-frame" "^7.0.0-beta.35" - chalk "^2.0.1" - micromatch "^2.3.11" - slash "^1.0.0" - stack-utils "^1.0.1" - jest-message-util@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-22.4.3.tgz#cf3d38aafe4befddbfc455e57d65d5239e399eb7" @@ -7086,18 +7093,10 @@ jest-message-util@^22.4.3: slash "^1.0.0" stack-utils "^1.0.1" -jest-mock@^22.2.0: - version "22.2.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-22.2.0.tgz#444b3f9488a7473adae09bc8a77294afded397a7" - jest-mock@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-22.4.3.tgz#f63ba2f07a1511772cdc7979733397df770aabc7" -jest-regex-util@^22.1.0: - version "22.1.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-22.1.0.tgz#5daf2fe270074b6da63e5d85f1c9acc866768f53" - jest-regex-util@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-22.4.3.tgz#a826eb191cdf22502198c5401a1fc04de9cef5af" @@ -7108,13 +7107,6 @@ jest-resolve-dependencies@^22.4.3: dependencies: jest-regex-util "^22.4.3" -jest-resolve@^22.4.2: - version "22.4.2" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-22.4.2.tgz#25d88aa4147462c9c1c6a1ba16250d3794c24d00" - dependencies: - browser-resolve "^1.11.2" - chalk "^2.0.1" - jest-resolve@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-22.4.3.tgz#0ce9d438c8438229aa9b916968ec6b05c1abb4ea" @@ -7167,17 +7159,6 @@ jest-serializer@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-22.4.3.tgz#a679b81a7f111e4766235f4f0c46d230ee0f7436" -jest-snapshot@^22.4.0: - version "22.4.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-22.4.0.tgz#03d3ce63f8fa7352388afc6a3c8b5ccc3a180ed7" - dependencies: - chalk "^2.0.1" - jest-diff "^22.4.0" - jest-matcher-utils "^22.4.0" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - pretty-format "^22.4.0" - jest-snapshot@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-22.4.3.tgz#b5c9b42846ffb9faccb76b841315ba67887362d2" @@ -7189,18 +7170,6 @@ jest-snapshot@^22.4.3: natural-compare "^1.4.0" pretty-format "^22.4.3" -jest-util@^22.4.1: - version "22.4.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-22.4.1.tgz#dd17c3bdb067f8e90591563ec0c42bf847dc249f" - dependencies: - callsites "^2.0.0" - chalk "^2.0.1" - graceful-fs "^4.1.11" - is-ci "^1.0.10" - jest-message-util "^22.4.0" - mkdirp "^0.5.1" - source-map "^0.6.0" - jest-util@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-22.4.3.tgz#c70fec8eec487c37b10b0809dc064a7ecf6aafac" @@ -7213,16 +7182,6 @@ jest-util@^22.4.3: mkdirp "^0.5.1" source-map "^0.6.0" -jest-validate@^22.4.2: - version "22.4.2" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-22.4.2.tgz#e789a4e056173bf97fe797a2df2d52105c57d4f4" - dependencies: - chalk "^2.0.1" - jest-config "^22.4.2" - jest-get-type "^22.1.0" - leven "^2.1.0" - pretty-format "^22.4.0" - jest-validate@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-22.4.3.tgz#0780954a5a7daaeec8d3c10834b9280865976b30" @@ -7338,7 +7297,7 @@ jpeg-js@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.2.0.tgz#53e448ec9d263e683266467e9442d2c5a2ef5482" -jquery@^3.1.1, jquery@^3.2.1, jquery@^3.3.1: +jquery@^3.1.1, jquery@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" @@ -7357,7 +7316,7 @@ js-yaml@3.4.1: argparse "~1.0.2" esprima "~2.2.0" -js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.5.1, js-yaml@^3.7.0, js-yaml@^3.9.1: +js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.1: version "3.11.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" dependencies: @@ -7454,6 +7413,10 @@ jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + json-loader@^0.5.4: version "0.5.7" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" @@ -7516,10 +7479,6 @@ jsonparse@^1.1.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -7571,6 +7530,10 @@ jszip@2.5.0: dependencies: pako "~0.2.5" +just-extend@^1.1.27: + version "1.1.27" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" + karma-chrome-launcher@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.1.1.tgz#216879c68ac04d8d5140e99619ba04b59afd46cf" @@ -7655,6 +7618,12 @@ keymirror@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/keymirror/-/keymirror-0.1.1.tgz#918889ea13f8d0a42e7c557250eee713adc95c35" +keyv@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" + dependencies: + json-buffer "3.0.0" + kilt@2.x.x: version "2.0.2" resolved "https://registry.yarnpkg.com/kilt/-/kilt-2.0.2.tgz#04d7183c298a1232efddf7ddca5959a8f6301e20" @@ -7747,9 +7716,9 @@ leaflet-responsive-popup@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/leaflet-responsive-popup/-/leaflet-responsive-popup-0.2.0.tgz#119bfcfae147864730f6a01fbd73b5b2ce274728" -leaflet-vega@0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/leaflet-vega/-/leaflet-vega-0.8.3.tgz#6d2572aa1909ed50d94937d5f4c2e42b018f4ac2" +leaflet-vega@^0.8.6: + version "0.8.6" + resolved "https://registry.yarnpkg.com/leaflet-vega/-/leaflet-vega-0.8.6.tgz#dd4090a6123cb983c2b732d53ec9e4daa53736b2" dependencies: vega-spec-injector "^0.0.2" @@ -7825,6 +7794,53 @@ linkify-it@^2.0.0: dependencies: uc.micro "^1.0.1" +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + +listr-update-renderer@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz#344d980da2ca2e8b145ba305908f32ae3f4cc8a7" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + strip-ansi "^3.0.1" + +listr-verbose-renderer@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" + dependencies: + chalk "^1.1.3" + cli-cursor "^1.0.2" + date-fns "^1.27.2" + figures "^1.7.0" + +listr@^0.14.1: + version "0.14.1" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.1.tgz#8a7afa4a7135cee4c921d128e0b7dfc6e522d43d" + dependencies: + "@samverschueren/stream-to-observable" "^0.3.0" + cli-truncate "^0.2.1" + figures "^1.7.0" + indent-string "^2.1.0" + is-observable "^1.1.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.4.0" + listr-verbose-renderer "^0.4.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + ora "^0.2.3" + p-map "^1.1.1" + rxjs "^6.1.0" + strip-ansi "^3.0.1" + livereload-js@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.3.0.tgz#c3ab22e8aaf5bf3505d80d098cbad67726548c9a" @@ -7883,7 +7899,7 @@ loader-runner@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" -loader-utils@^1.0.2, loader-utils@^1.1.0: +loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" dependencies: @@ -8060,7 +8076,7 @@ lodash.isempty@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" -lodash.isequal@^4.0.0, lodash.isequal@^4.1.1: +lodash.isequal@^4.0.0, lodash.isequal@^4.1.1, lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -8182,20 +8198,37 @@ lodash@4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@^4.8.2, lodash@~4.17.4, lodash@~4.17.5: +lodash@^4.0.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@^4.8.2, lodash@~4.17.4, lodash@~4.17.5: version "4.17.5" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" +lodash@^4.17.10: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + lodash@~4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.3.0.tgz#efd9c4a6ec53f3b05412429915c3e4824e4d25a4" +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + dependencies: + chalk "^1.0.0" + log-symbols@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" dependencies: chalk "^2.0.1" +log-update@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" + dependencies: + ansi-escapes "^1.0.0" + cli-cursor "^1.0.2" + log4js@^0.6.31: version "0.6.38" resolved "https://registry.yarnpkg.com/log4js/-/log4js-0.6.38.tgz#2c494116695d6fb25480943d3fc872e662a522fd" @@ -8203,15 +8236,19 @@ log4js@^0.6.31: readable-stream "~1.0.2" semver "~4.3.3" -lolex@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" +loglevel@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" + +lolex@^2.2.0, lolex@^2.3.2: + version "2.6.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.6.0.tgz#cf9166f3c9dece3cdeb5d6b01fce50f14a1203e3" longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.0, loose-envify@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" dependencies: @@ -8224,7 +8261,7 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" -lowercase-keys@^1.0.0: +lowercase-keys@1.0.0, lowercase-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" @@ -8283,6 +8320,10 @@ make-dir@^1.0.0: dependencies: pify "^3.0.0" +make-error@^1.1.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.4.tgz#19978ed575f9e9545d2ff8c13e33b5d18a67d535" + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -8326,15 +8367,15 @@ markdown-escapes@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.1.tgz#1994df2d3af4811de59a6714934c2b2292734518" -markdown-it@8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.3.2.tgz#df4b86530d17c3bc9beec3b68d770b92ea17ae96" +markdown-it@^8.4.1: + version "8.4.1" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.1.tgz#206fe59b0e4e1b78a7c73250af9b34a4ad0aaf44" dependencies: argparse "^1.0.7" entities "~1.1.1" linkify-it "^2.0.0" mdurl "^1.0.1" - uc.micro "^1.0.3" + uc.micro "^1.0.5" marked-text-renderer@0.1.0: version "0.1.0" @@ -8423,21 +8464,6 @@ methods@^1.1.1, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" -micro-compress@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micro-compress/-/micro-compress-1.0.0.tgz#53f5a80b4ad0320ca165a559b6e3df145d4f704f" - dependencies: - compression "^1.6.2" - -micro@9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/micro/-/micro-9.1.0.tgz#f2effba306639076e994c007c327dfc36a5185e9" - dependencies: - content-type "1.0.4" - is-stream "1.1.0" - mri "1.1.0" - raw-body "2.3.2" - micromatch@^2.1.5, micromatch@^2.3.11: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -8481,11 +8507,11 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.x.x, "mime-db@>= 1.33.0 < 2", mime-db@~1.33.0: +mime-db@1.x.x, mime-db@~1.33.0: version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" -mime-types@2.1.18, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: +mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: version "2.1.18" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" dependencies: @@ -8495,10 +8521,6 @@ mime@1.3.x: version "1.3.6" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0" -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - mime@^1.2.11, mime@^1.3.4, mime@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -8507,6 +8529,10 @@ mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" +mimic-response@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" + mimos@3.x.x: version "3.0.3" resolved "https://registry.yarnpkg.com/mimos/-/mimos-3.0.3.tgz#b9109072ad378c2b72f6a0101c43ddfb2b36641f" @@ -8605,21 +8631,6 @@ mkdirp@^0.3.5, mkdirp@~0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7" -mocha@*: - version "5.0.4" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.4.tgz#6b7aa328472da1088e69d47e75925fd3a3bb63c6" - dependencies: - browser-stdout "1.3.1" - commander "2.11.0" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.3" - he "1.1.1" - mkdirp "0.5.1" - supports-color "4.4.0" - mocha@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.3.0.tgz#d29b7428d3f52c82e2e65df1ecb7064e1aabbfb5" @@ -8658,10 +8669,6 @@ moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.20.1: version "2.21.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a" -mri@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.0.tgz#5c0a3f29c8ccffbbb1ec941dcec09d71fa32f36a" - ms@0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.0.tgz#865be94c2e7397ad8a57da6a633a6e2f30798b83" @@ -8678,7 +8685,7 @@ ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -ms@2.1.1, ms@^2.0.0: +ms@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" @@ -8786,6 +8793,16 @@ nigel@2.x.x: hoek "4.x.x" vise "2.x.x" +nise@^1.2.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.3.3.tgz#c17a850066a8a1dfeb37f921da02441afc4a82ba" + dependencies: + "@sinonjs/formatio" "^2.0.0" + just-extend "^1.1.27" + lolex "^2.3.2" + path-to-regexp "^1.7.0" + text-encoding "^0.6.4" + no-ui-slider@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/no-ui-slider/-/no-ui-slider-1.2.0.tgz#1f64f5a8b82e6786f3261d82b0cc99b598817e69" @@ -8809,7 +8826,7 @@ node-fetch@1.3.2: dependencies: encoding "^0.1.11" -node-fetch@^1.0.1: +node-fetch@^1.0.1, node-fetch@^1.3.3: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" dependencies: @@ -8881,9 +8898,9 @@ node-status-codes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f" -node-version@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.1.0.tgz#f437d7ba407e65e2c4eaef8887b1718ba523d4f0" +nodemailer@^4.6.4: + version "4.6.4" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-4.6.4.tgz#f0d72d0c6a6ec5f4369fa8f4bf5127a31baa2014" nomnom@~1.6.2: version "1.6.2" @@ -8936,6 +8953,14 @@ normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" +normalize-url@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" + dependencies: + prepend-http "^2.0.0" + query-string "^5.0.1" + sort-keys "^2.0.0" + normalize-url@^1.4.0: version "1.9.1" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" @@ -9108,10 +9133,6 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -on-headers@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" - once@1.x, once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -9126,17 +9147,7 @@ onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" dependencies: - mimic-fn "^1.0.0" - -openssl-self-signed-certificate@1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/openssl-self-signed-certificate/-/openssl-self-signed-certificate-1.1.6.tgz#9d3a4776b1a57e9847350392114ad2f915a83dd4" - -opn@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.2.0.tgz#71fdf934d6827d676cecbea1531f95d354641225" - dependencies: - is-wsl "^1.1.0" + mimic-fn "^1.0.0" optimist@^0.6.1, optimist@~0.6.1: version "0.6.1" @@ -9166,6 +9177,15 @@ options@>=0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" +ora@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" + dependencies: + chalk "^1.1.1" + cli-cursor "^1.0.2" + cli-spinners "^0.1.2" + object-assign "^4.0.1" + ora@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ora/-/ora-1.4.0.tgz#884458215b3a5d4097592285f93321bb7a79e2e5" @@ -9208,10 +9228,26 @@ osenv@^0.1.0, osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + +p-cancelable@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" +p-is-promise@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" + p-limit@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" @@ -9228,6 +9264,22 @@ p-map@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" +p-queue@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-2.4.2.tgz#03609826682b743be9a22dba25051bd46724fc34" + +p-retry@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-1.0.0.tgz#3927332a4b7d70269b535515117fc547da1a6968" + dependencies: + retry "^0.10.0" + +p-timeout@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" + dependencies: + p-finally "^1.0.0" + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -9389,7 +9441,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1, path-is-absolute@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@1.0.2, path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" @@ -9414,12 +9466,6 @@ path-to-regexp@^1.0.0, path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" -path-type@3.0.0, path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - dependencies: - pify "^3.0.0" - path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -9434,6 +9480,12 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + dependencies: + pify "^3.0.0" + pause-stream@0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" @@ -9566,10 +9618,6 @@ pkg-up@^2.0.0: dependencies: find-up "^2.1.0" -pkginfo@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" - plugin-error@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" @@ -9583,10 +9631,6 @@ pluralize@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-3.1.0.tgz#84213d0a12356069daa84060c559242633161368" -pluralize@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" - pluralize@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" @@ -9607,6 +9651,10 @@ pngjs@^3.0.0: version "3.3.2" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.2.tgz#097c3c2a75feb223eadddea6bc9f0050cf830bc3" +popper.js@^1.14.1: + version "1.14.3" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -9897,25 +9945,18 @@ prepend-http@^1.0.0, prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -prettier@^1.10.2, prettier@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.1.tgz#61e43fc4cd44e68f2b0dfc2c38cd4bb0fccdcc75" - prettier@^1.12.1: version "1.12.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325" -pretty-format@^22.4.0: - version "22.4.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-22.4.0.tgz#237b1f7e1c50ed03bc65c03ccc29d7c8bb7beb94" - dependencies: - ansi-regex "^3.0.0" - ansi-styles "^3.2.0" - pretty-format@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-22.4.3.tgz#f873d780839a9c02e9664c8a082e9ee79eaac16f" @@ -9927,7 +9968,7 @@ prismjs@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-0.0.1.tgz#0fd50f4baf26e5cd33523b65bac2f0bc90f5503f" -private@^0.1.6, private@^0.1.7: +private@^0.1.6, private@^0.1.7, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -9999,9 +10040,9 @@ proxy-from-env@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" -proxyquire@1.7.10: - version "1.7.10" - resolved "https://registry.yarnpkg.com/proxyquire/-/proxyquire-1.7.10.tgz#75be0770a81188f4d08bd01dfc30b767365aa20d" +proxyquire@1.7.11: + version "1.7.11" + resolved "https://registry.yarnpkg.com/proxyquire/-/proxyquire-1.7.11.tgz#13b494eb1e71fb21cc3ebe3699e637d3bec1af9e" dependencies: fill-keys "^1.0.2" module-not-found-error "^1.0.0" @@ -10118,6 +10159,14 @@ query-string@^4.1.0: object-assign "^4.1.0" strict-uri-encode "^1.0.0" +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + querystring-browser@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/querystring-browser/-/querystring-browser-1.0.4.tgz#f2e35881840a819bc7b1bf597faf0979e6622dc6" @@ -10179,7 +10228,7 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -range-parser@^1.2.0, range-parser@~1.2.0: +range-parser@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" @@ -10260,7 +10309,16 @@ react-color@^2.13.8: reactcss "^1.2.0" tinycolor2 "^1.4.1" -react-dom@^16.0.0, react-dom@^16.2.0: +react-datepicker@v1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-1.4.1.tgz#ee171b71d9853e56f9eece5fc3186402f4648683" + dependencies: + classnames "^2.2.5" + prop-types "^15.6.0" + react-onclickoutside "^6.7.1" + react-popper "^0.9.1" + +react-dom@^16.0.0: version "16.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044" dependencies: @@ -10269,6 +10327,15 @@ react-dom@^16.0.0, react-dom@^16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" +react-dom@^16.3.0: + version "16.3.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.3.2.tgz#cb90f107e09536d683d84ed5d4888e9640e0e4df" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.0" + react-draggable@3.x, "react-draggable@^2.2.6 || ^3.0.3": version "3.0.5" resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-3.0.5.tgz#c031e0ed4313531f9409d6cd84c8ebcec0ddfe2d" @@ -10324,6 +10391,17 @@ react-motion@^0.5.2: prop-types "^15.5.8" raf "^3.1.0" +react-onclickoutside@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.7.1.tgz#6a5b5b8b4eae6b776259712c89c8a2b36b17be93" + +react-popper@^0.9.1: + version "0.9.5" + resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-0.9.5.tgz#02a24ef3eec33af9e54e8358ab70eb0e331edd05" + dependencies: + popper.js "^1.14.1" + prop-types "^15.6.1" + react-portal@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-3.2.0.tgz#4224e19b2b05d5cbe730a7ba0e34ec7585de0043" @@ -10339,6 +10417,14 @@ react-reconciler@^0.7.0: object-assign "^4.1.1" prop-types "^15.6.0" +react-redux-request@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/react-redux-request/-/react-redux-request-1.5.5.tgz#693562b0d85293d9d16b02e13ea13f118950bb1d" + dependencies: + lodash.get "^4.4.2" + lodash.isequal "^4.5.0" + prop-types "^15.6.1" + react-redux@^5.0.5, react-redux@^5.0.6: version "5.0.7" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" @@ -10384,7 +10470,7 @@ react-router@^4.2.0: prop-types "^15.5.4" warning "^3.0.0" -react-select@^1.2.0, react-select@^1.2.1: +react-select@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.2.1.tgz#a2fe58a569eb14dcaa6543816260b97e538120d1" dependencies: @@ -10429,6 +10515,16 @@ react-toggle@4.0.2: dependencies: classnames "^2.2.5" +react-virtualized@^9.18.5: + version "9.18.5" + resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.18.5.tgz#42dd390ebaa7ea809bfcaf775d39872641679b89" + dependencies: + babel-runtime "^6.26.0" + classnames "^2.2.3" + dom-helpers "^2.4.0 || ^3.0.0" + loose-envify "^1.3.0" + prop-types "^15.6.0" + react-vis@^1.8.1: version "1.9.2" resolved "https://registry.yarnpkg.com/react-vis/-/react-vis-1.9.2.tgz#4dbd5d91ac820fd39fa7ad1c892198495194f6e3" @@ -10459,6 +10555,15 @@ react@>=0.13.3, react@^16.2.0: object-assign "^4.1.1" prop-types "^15.6.0" +react@^16.3.0: + version "16.3.2" + resolved "https://registry.yarnpkg.com/react/-/react-16.3.2.tgz#fdc8420398533a1e58872f59091b272ce2f91ea9" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.0" + reactcss@1.2.3, reactcss@^1.2.0: version "1.2.3" resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.3.tgz#c00013875e557b1cf0dfd9a368a1c3dab3b548dd" @@ -10594,12 +10699,6 @@ realpath-native@^1.0.0: dependencies: util.promisify "^1.0.0" -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - dependencies: - resolve "^1.1.6" - redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" @@ -10888,7 +10987,7 @@ require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" -require-uncached@^1.0.2, require-uncached@^1.0.3: +require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" dependencies: @@ -10945,13 +11044,13 @@ resolve@1.1.7, resolve@1.1.x, resolve@~1.1.0, resolve@~1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.5.0: +resolve@^1.1.5, resolve@^1.1.7, resolve@^1.2.0, resolve@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.6.0.tgz#0fbd21278b27b4004481c395349e7aba60a9ff5c" dependencies: path-parse "^1.0.5" -resolve@^1.7.1: +resolve@^1.3.2, resolve@^1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" dependencies: @@ -10961,6 +11060,12 @@ resolve@~0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.3.1.tgz#34c63447c664c70598d1c9b126fc43b2a24310a4" +responselike@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + dependencies: + lowercase-keys "^1.0.0" + restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -10985,6 +11090,10 @@ ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" +retry@^0.10.0, retry@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" @@ -11077,7 +11186,19 @@ rxjs@5.4.3: dependencies: symbol-observable "^1.0.1" -safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +rxjs@^5.4.3: + version "5.5.10" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.10.tgz#fde02d7a614f6c8683d0d1957827f492e09db045" + dependencies: + symbol-observable "1.0.1" + +rxjs@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.1.0.tgz#833447de4e4f6427b9cec3e5eb9f56415cd28315" + dependencies: + tslib "^1.9.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -11098,13 +11219,9 @@ safefs@^4.0.0: editions "^1.1.1" graceful-fs "^4.1.4" -samsam@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" - -samsam@~1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621" +samsam@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" sane@^2.0.0: version "2.5.0" @@ -11182,7 +11299,7 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" @@ -11194,55 +11311,6 @@ semver@~4.3.3: version "4.3.6" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" -semver@~5.0.1: - version "5.0.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" - -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" - -serve@^6.3.1: - version "6.5.3" - resolved "https://registry.yarnpkg.com/serve/-/serve-6.5.3.tgz#39ae7b7ff5934a9ca93ba7235344eb34b726cc48" - dependencies: - "@zeit/check-updates" "1.1.0" - args "3.0.8" - basic-auth "2.0.0" - bluebird "3.5.1" - boxen "1.3.0" - chalk "2.3.2" - clipboardy "1.2.3" - dargs "5.1.0" - detect-port "1.2.2" - filesize "3.6.0" - fs-extra "5.0.0" - handlebars "4.0.11" - ip "1.1.5" - micro "9.1.0" - micro-compress "1.0.0" - mime-types "2.1.18" - node-version "1.1.0" - openssl-self-signed-certificate "1.1.6" - opn "5.2.0" - path-is-inside "1.0.2" - path-type "3.0.0" - send "0.16.2" - set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -11307,14 +11375,6 @@ shell-quote@^1.6.1: array-reduce "~0.0.0" jsonify "~0.0.0" -shelljs@^0.7.5: - version "0.7.8" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - shellwords@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" @@ -11350,14 +11410,17 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -sinon@1.17.2: - version "1.17.2" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.2.tgz#c1ea67b84a1e7b3350f6c4713efacef8e4ae8b71" +sinon@^5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-5.0.7.tgz#3bded6a73613ccc9e512e20246ced69a27c27dab" dependencies: - formatio "1.1.1" - lolex "1.3.2" - samsam "1.1.2" - util ">=0.10.3 <1" + "@sinonjs/formatio" "^2.0.0" + diff "^3.1.0" + lodash.get "^4.4.2" + lolex "^2.2.0" + nise "^1.2.0" + supports-color "^5.1.0" + type-detect "^4.0.5" slash@^1.0.0: version "1.0.0" @@ -11466,6 +11529,12 @@ sort-keys@^1.0.0: dependencies: is-plain-obj "^1.0.0" +sort-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" + dependencies: + is-plain-obj "^1.0.0" + source-list-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" @@ -11507,6 +11576,13 @@ source-map-support@^0.5.0: dependencies: source-map "^0.6.0" +source-map-support@^0.5.3, source-map-support@^0.5.5: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" @@ -11717,7 +11793,7 @@ static-module@^2.2.0: static-eval "^2.0.0" through2 "~2.0.3" -statuses@1, "statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2", statuses@~1.4.0: +statuses@1, "statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2": version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" @@ -11789,12 +11865,6 @@ string-length@^2.0.0: astral-regex "^1.0.0" strip-ansi "^4.0.0" -string-similarity@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-1.2.0.tgz#d75153cb383846318b7a39a8d9292bb4db4e9c30" - dependencies: - lodash "^4.13.1" - string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -11947,11 +12017,11 @@ superagent@^3.0.0: qs "^6.5.1" readable-stream "^2.0.5" -supertest-as-promised@2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/supertest-as-promised/-/supertest-as-promised-2.0.2.tgz#a5da49df1b650d28338235f37f295360a81fc9b4" +supertest-as-promised@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/supertest-as-promised/-/supertest-as-promised-4.0.2.tgz#0464f2bd256568d4a59bce84269c0548f6879f1a" dependencies: - bluebird "^2.9.24" + bluebird "^3.3.1" methods "^1.1.1" supertest@3.0.0: @@ -11967,12 +12037,6 @@ supports-color@3.1.2: dependencies: has-flag "^1.0.0" -supports-color@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - dependencies: - has-flag "^2.0.0" - supports-color@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" @@ -11993,6 +12057,12 @@ supports-color@^4.0.0, supports-color@^4.2.1: dependencies: has-flag "^2.0.0" +supports-color@^5.1.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + supports-color@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" @@ -12011,7 +12081,11 @@ svgo@^0.7.0: sax "~1.2.1" whet.extend "~0.9.9" -symbol-observable@^1.0.1, symbol-observable@^1.0.3: +symbol-observable@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" + +symbol-observable@^1.0.1, symbol-observable@^1.0.3, symbol-observable@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" @@ -12027,17 +12101,6 @@ tabbable@^1.0.3, tabbable@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-1.1.2.tgz#b171680aea6e0a3e9281ff23532e2e5de11c0d94" -table@^3.7.8: - version "3.8.3" - resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" - dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" - table@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc" @@ -12074,6 +12137,15 @@ tar-fs@^1.16.0: pump "^1.0.0" tar-stream "^1.1.2" +tar-fs@^1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.2.tgz#17e5239747e399f7e77344f5f53365f04af53577" + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + tar-pack@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" @@ -12128,7 +12200,7 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" -test-exclude@^4.1.1: +test-exclude@^4.1.1, test-exclude@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.1.tgz#dfa222f03480bca69207ca728b37d74b45f724fa" dependencies: @@ -12142,6 +12214,10 @@ tether@^1.3.7: version "1.4.3" resolved "https://registry.yarnpkg.com/tether/-/tether-1.4.3.tgz#fd547024c47b6e5c9b87e1880f997991a9a6ad54" +text-encoding@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -12182,7 +12258,7 @@ timed-out@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a" -timed-out@^4.0.0: +timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" @@ -12352,11 +12428,7 @@ traverse@0.6.6: version "0.6.6" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" -tree-kill@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.1.0.tgz#c963dcf03722892ec59cba569e940b71954d1729" - -tree-kill@^1.2.0: +tree-kill@^1.1.0, tree-kill@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" @@ -12412,24 +12484,87 @@ trunc-text@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/trunc-text/-/trunc-text-1.0.2.tgz#b582bb3ddea9c9adc25017d737c48ebdd2157406" -ts-jest@^22.4.3: - version "22.4.3" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-22.4.3.tgz#5c06b89359e598d97f08802936ea400be555a9d1" +ts-jest@^22.4.6: + version "22.4.6" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-22.4.6.tgz#a5d7f5e8b809626d1f4143209d301287472ec344" dependencies: - babel-core "^6.26.0" - babel-plugin-istanbul "^4.1.4" - babel-plugin-transform-es2015-modules-commonjs "^6.26.0" - babel-preset-jest "^22.4.0" + babel-core "^6.26.3" + babel-plugin-istanbul "^4.1.6" + babel-plugin-transform-es2015-modules-commonjs "^6.26.2" + babel-preset-jest "^22.4.3" cpx "^1.5.0" - fs-extra "4.0.3" - jest-config "^22.4.2" + fs-extra "6.0.0" + jest-config "^22.4.3" + lodash "^4.17.10" pkg-dir "^2.0.0" + source-map-support "^0.5.5" yargs "^11.0.0" +ts-loader@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-3.5.0.tgz#151d004dcddb4cf8e381a3bf9d6b74c2d957a9c0" + dependencies: + chalk "^2.3.0" + enhanced-resolve "^3.0.0" + loader-utils "^1.0.2" + micromatch "^3.1.4" + semver "^5.0.1" + +ts-node@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-6.0.3.tgz#28bf74bcad134fad17f7469dad04638ece03f0f4" + dependencies: + arrify "^1.0.0" + chalk "^2.3.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.3" + yn "^2.0.0" + +tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.1.tgz#a5d1f0532a49221c87755cfcc89ca37197242ba7" + tslib@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" +tslint-config-prettier@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.12.0.tgz#bc8504f286ecf42b906f3d1126a093114f5729cc" + +tslint-plugin-prettier@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/tslint-plugin-prettier/-/tslint-plugin-prettier-1.3.0.tgz#7eb65d19ea786a859501a42491b78c5de2031a3f" + dependencies: + eslint-plugin-prettier "^2.2.0" + tslib "^1.7.1" + +tslint@^5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.10.0.tgz#11e26bccb88afa02dd0d9956cae3d4540b5f54c3" + dependencies: + babel-code-frame "^6.22.0" + builtin-modules "^1.1.1" + chalk "^2.3.0" + commander "^2.12.1" + diff "^3.2.0" + glob "^7.1.1" + js-yaml "^3.7.0" + minimatch "^3.0.4" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.8.0" + tsutils "^2.12.1" + +tsutils@^2.12.1: + version "2.27.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.27.0.tgz#9efb252b188eaa0ca3ade41dc410d6ce7eaab816" + dependencies: + tslib "^1.8.1" + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -12458,6 +12593,10 @@ type-detect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" +type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + type-is@~1.6.0, type-is@~1.6.10, type-is@~1.6.15: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" @@ -12475,15 +12614,15 @@ typedarray@^0.0.6, typedarray@~0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624" +typescript@^2.8.3: + version "2.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170" ua-parser-js@^0.7.9: version "0.7.17" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" -uc.micro@^1.0.1, uc.micro@^1.0.3: +uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376" @@ -12692,7 +12831,19 @@ upath@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.4.tgz#ee2321ba0a786c50973db043a50b7bcba822361d" -update-notifier@2.3.0, update-notifier@^2.2.0: +update-notifier@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc" + dependencies: + chalk "^1.0.0" + configstore "^1.0.0" + is-npm "^1.0.0" + latest-version "^1.0.0" + repeating "^1.1.2" + semver-diff "^2.0.0" + string-length "^1.0.0" + +update-notifier@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451" dependencies: @@ -12706,22 +12857,14 @@ update-notifier@2.3.0, update-notifier@^2.2.0: semver-diff "^2.0.0" xdg-basedir "^3.0.0" -update-notifier@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc" - dependencies: - chalk "^1.0.0" - configstore "^1.0.0" - is-npm "^1.0.0" - latest-version "^1.0.0" - repeating "^1.1.2" - semver-diff "^2.0.0" - string-length "^1.0.0" - urix@^0.1.0, urix@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" +url-join@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.0.tgz#4d3340e807d3773bda9991f8305acdcc2a665d2a" + url-loader@0.5.9: version "0.5.9" resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-0.5.9.tgz#cc8fea82c7b906e7777019250869e569e995c295" @@ -12735,6 +12878,12 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + dependencies: + prepend-http "^2.0.0" + url-regex@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/url-regex/-/url-regex-3.2.0.tgz#dbad1e0c9e29e105dd0b1f09f6862f7fdb482724" @@ -12786,7 +12935,7 @@ util.promisify@^1.0.0: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" -util@0.10.3, "util@>=0.10.3 <1", util@^0.10.3: +util@0.10.3, util@^0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" dependencies: @@ -12808,6 +12957,12 @@ uuid@^3.0.0, uuid@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" +val-loader@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/val-loader/-/val-loader-1.1.0.tgz#ed91537424d62a4ded98e846ccf07367756bf506" + dependencies: + loader-utils "^1.0.0" + validate-npm-package-license@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" @@ -12829,10 +12984,6 @@ value-or-function@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - vega-canvas@1: version "1.0.1" resolved "https://registry.yarnpkg.com/vega-canvas/-/vega-canvas-1.0.1.tgz#22cfa510af0cfbd920fc6af8b6111d3de5e63c44" @@ -12845,16 +12996,16 @@ vega-crossfilter@2: vega-dataflow "3" vega-util "1" -vega-dataflow@3: - version "3.0.5" - resolved "https://registry.yarnpkg.com/vega-dataflow/-/vega-dataflow-3.0.5.tgz#01c52b3fbb7c33eab1c4396fc06d89d90a85a4fb" +vega-dataflow@3, vega-dataflow@^3.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/vega-dataflow/-/vega-dataflow-3.1.0.tgz#1021d14f9d080403cb2a85801a6a70cd79d2f916" dependencies: vega-loader "2" vega-util "1" vega-encode@2: - version "2.0.7" - resolved "https://registry.yarnpkg.com/vega-encode/-/vega-encode-2.0.7.tgz#c69738784f204850ae82ddf462ce86ebd86110bc" + version "2.0.8" + resolved "https://registry.yarnpkg.com/vega-encode/-/vega-encode-2.0.8.tgz#0c6b377bf4b20df2b0a28c4d12b2fea65ab28e56" dependencies: d3-array "1" d3-format "1" @@ -12882,8 +13033,8 @@ vega-force@2: vega-util "1" vega-geo@^2.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/vega-geo/-/vega-geo-2.2.0.tgz#0fcd3b2c73de759edafeac3d9a2332ae0b4afd72" + version "2.2.2" + resolved "https://registry.yarnpkg.com/vega-geo/-/vega-geo-2.2.2.tgz#d45dd6b843696618e9b6bd646ebcc711029975dc" dependencies: d3-array "1" d3-contour "1" @@ -12893,17 +13044,17 @@ vega-geo@^2.2: vega-util "1" vega-hierarchy@^2.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/vega-hierarchy/-/vega-hierarchy-2.1.1.tgz#01b89fa70352e61dff5666123a653e163f742a55" + version "2.1.2" + resolved "https://registry.yarnpkg.com/vega-hierarchy/-/vega-hierarchy-2.1.2.tgz#36d7ecb279d3df055853d8ca052198cc94cbde24" dependencies: d3-collection "1" d3-hierarchy "1" - vega-dataflow "3" + vega-dataflow "^3.1" vega-util "1" -vega-lib@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/vega-lib/-/vega-lib-3.2.1.tgz#feca4b054a0db492f92fd555e6c20be3f3c117d0" +vega-lib@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/vega-lib/-/vega-lib-3.3.1.tgz#b5f09974f414ade0c5ac6c5ee250f34d61f5ff2b" dependencies: vega-crossfilter "2" vega-dataflow "3" @@ -12927,15 +13078,15 @@ vega-lib@^3.2.1: vega-voronoi "2" vega-wordcloud "^2.1" -vega-lite@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/vega-lite/-/vega-lite-2.3.1.tgz#a7abd16ef7d06b3f8ed8c873bca4be5c4a577369" +vega-lite@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/vega-lite/-/vega-lite-2.4.0.tgz#e2bd0eabf5288c470a698377a10d4118f4f610e1" dependencies: "@types/json-stable-stringify" "^1.0.32" json-stable-stringify "^1.0.1" tslib "^1.9.0" vega-event-selector "^2.0.0" - vega-typings "^0.2.11" + vega-typings "^0.2.15" vega-util "^1.7.0" yargs "^11.0.0" @@ -12950,8 +13101,8 @@ vega-loader@2: vega-util "1" vega-parser@2, vega-parser@^2.5: - version "2.6.1" - resolved "https://registry.yarnpkg.com/vega-parser/-/vega-parser-2.6.1.tgz#7cde99153392c7452c53cac2c9d0726aead72912" + version "2.7.0" + resolved "https://registry.yarnpkg.com/vega-parser/-/vega-parser-2.7.0.tgz#974a7c4cd877eafd07b425f842b1ce83cc18e3cf" dependencies: d3-array "1" d3-color "1" @@ -12967,8 +13118,8 @@ vega-parser@2, vega-parser@^2.5: vega-util "^1.7" vega-projection@1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vega-projection/-/vega-projection-1.0.1.tgz#da517ac02ad14389c6d98c65992bd5d1568e1c35" + version "1.1.0" + resolved "https://registry.yarnpkg.com/vega-projection/-/vega-projection-1.1.0.tgz#46452fd12927201d1a7f7ef8f61d6e24253dbcd2" dependencies: d3-geo "1" @@ -12991,8 +13142,8 @@ vega-scale@2, vega-scale@^2.1: vega-util "1" vega-scenegraph@2, vega-scenegraph@^2.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/vega-scenegraph/-/vega-scenegraph-2.3.1.tgz#73c4394910729782e8a75cf3eae66e1d8205089b" + version "2.4.2" + resolved "https://registry.yarnpkg.com/vega-scenegraph/-/vega-scenegraph-2.4.2.tgz#1835c63a66984a368633dfcfd8fa7495ee12ff25" dependencies: d3-path "1" d3-shape "1" @@ -13014,36 +13165,41 @@ vega-statistics@^1.2: dependencies: d3-array "1" +vega-tooltip@^0.9.14: + version "0.9.14" + resolved "https://registry.yarnpkg.com/vega-tooltip/-/vega-tooltip-0.9.14.tgz#c10bcacf69bf60a02c598ec46b905f94f28c54ac" + dependencies: + json-stringify-safe "^5.0.1" + vega-util "^1.7.0" + vega-transforms@^1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/vega-transforms/-/vega-transforms-1.3.0.tgz#b2afd3b2b8e2de35177fc91c506f73bbf4f9738b" + version "1.3.1" + resolved "https://registry.yarnpkg.com/vega-transforms/-/vega-transforms-1.3.1.tgz#c570702760917a007a12cb35df9387270bfb6b21" dependencies: d3-array "1" vega-dataflow "3" vega-statistics "^1.2" vega-util "1" -vega-typings@*, vega-typings@^0.2.11: - version "0.2.11" - resolved "https://registry.yarnpkg.com/vega-typings/-/vega-typings-0.2.11.tgz#efc86024e50d69b120dc66165fb654caaa4dbbe5" - dependencies: - prettier "^1.10.2" +vega-typings@*, vega-typings@^0.2.15: + version "0.2.15" + resolved "https://registry.yarnpkg.com/vega-typings/-/vega-typings-0.2.15.tgz#7c973f7f342efe82fb9c4ad96833431c11cd5911" vega-util@1, vega-util@^1.7, vega-util@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/vega-util/-/vega-util-1.7.0.tgz#0ca0512bb8dcc6541165c34663d115d0712e0cf1" vega-view-transforms@^1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vega-view-transforms/-/vega-view-transforms-1.2.0.tgz#5c184a747815bec12ba800ec4a3212681a9d7f35" + version "1.2.1" + resolved "https://registry.yarnpkg.com/vega-view-transforms/-/vega-view-transforms-1.2.1.tgz#6114e621e5cc9e59f9db1ecc08a90e23385630d4" dependencies: vega-dataflow "3" vega-scenegraph "2" vega-util "1" vega-view@^2.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/vega-view/-/vega-view-2.2.1.tgz#f232a2a199483d49e96bfce3936c9613b4892475" + version "2.3.2" + resolved "https://registry.yarnpkg.com/vega-view/-/vega-view-2.3.2.tgz#037040b8e64d9dbf7900e86bbc8e952f0b99a119" dependencies: d3-array "1" vega-dataflow "3" @@ -13473,7 +13629,7 @@ ws@2.0.x: dependencies: ultron "~1.1.0" -ws@^4.0.0: +ws@^4.0.0, ws@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" dependencies: @@ -13527,7 +13683,7 @@ xml-parse-from-string@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" -xml2js@0.4.19, xml2js@^0.4.5: +xml2js@^0.4.19, xml2js@^0.4.5: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" dependencies: @@ -13691,6 +13847,10 @@ yeast@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" + zlib@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/zlib/-/zlib-1.0.5.tgz#6e7c972fc371c645a6afb03ab14769def114fcc0"